Skip to content

ShivanshTiwari613/Planning-Agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PlanAct

A minimal, readable ReAct-style agent that plans, executes tools in a sandbox, observes results, and recovers from failures. Built to be a clean reference implementation you can actually read in an afternoon.

User input ─► Plan (LLM, JSON steps)
             └─► for each step:
                    Analyze  ─►  Execute tool  ─►  Observe  ─►  Update context
                                     │
                                     └─ on failure ─► Recovery steps
             └─► Final synthesis

Features

  • Plan-then-act loop with an explicit OODA-style iteration per step
  • Pluggable tools — ships with:
    • terminal_exec — shell commands, read_file, write_file
    • python_runner — executes Python with auto-install on ModuleNotFoundError and LLM-driven self-heal on runtime errors
  • E2B sandbox for safe, isolated execution
  • Live workspace sync — files written by the agent appear under output_workspaces/<plan_id>/ in real time
  • Structured LLM output channels via <analysis> / <final> tags
  • Multi-provider LLM client — Google Gemini (default), Anthropic, OpenAI, DeepSeek
  • Streaming event callback for CLI or API integration (thought, tool_start, tool_end, answer, error)

Project layout

app/
  agent/
    session_manager.py      # conversation → plan orchestration
    session_context.py      # per-session state
  flow/
    planning.py             # plan → OODA loop → synthesis
    tool_executor.py        # tool dispatch, placeholder resolution
    context_manager.py      # LLM-summarized step memory
    recovery.py             # error-recovery step generation
    helpers/workspace_sync.py
  tool/
    base.py                 # BaseTool, ToolResult
    terminal_tool.py
    python_runner_tool.py
  sandbox/
    e2b_handler.py          # sandbox lifecycle
  llm/                      # provider clients
  prompt/                   # system + planner prompts
  api/schema.py             # AgentEvent protocol
  schema.py                 # Plan, PlanStep, ContextObject, Message
config/settings.py
main.py                     # CLI entry point
server.py                   # API entry point (stub)

Installation

git clone <this-repo>
cd planact
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# edit .env and fill in E2B_API_KEY + your chosen LLM provider key

You need:

  • An E2B API key for the sandbox.
  • At least one LLM API key (Gemini by default; set LLM_PROVIDER to switch).

Usage

CLI

python main.py

Then type a task:

User > scrape the top 5 HN stories and save them to hn.json

You'll see color-coded events:

  • Cyan [ANALYSIS] — the agent's reasoning for the current step
  • Yellow 🛠️ TOOL_NAME... — tool invocation
  • Dim └── Result: ... — tool output summary
  • Green PlanAct > ... — final answer

Generated files land under output_workspaces/<plan_id>/.

Programmatic

from app.agent.session_manager import SessionManager
from app.tool.terminal_tool import TerminalTool
from app.tool.python_runner_tool import PythonRunnerTool

manager = SessionManager(
    available_tools=[TerminalTool(), PythonRunnerTool()],
    on_event=my_event_handler,   # async callable(AgentEvent)
)
answer = await manager.process_message_from_api("write a fibonacci script and run it")

How it works

  1. Plan. The LLM emits a JSON plan — an array of {tool_name, tool_args, description} steps. Plans are generated once at the start of a task; each step is self-contained.
  2. Analyze. Before executing a step, the LLM writes short <analysis> reasoning about what the step should accomplish given the context so far.
  3. Execute. ToolExecutor resolves {{step_id.output}} placeholders against previous results, then calls the tool inside the E2B sandbox.
  4. Observe. The workspace is synced to the local output_workspaces/ directory after every step, so you can inspect files as the agent works.
  5. Update context. ContextManager uses the LLM to keep a rolling summary of what has been learned, bounding context growth.
  6. Recover. On tool failure, recovery.generate_recovery_steps() asks the LLM for replacement steps. python_runner additionally self-heals missing packages and simple runtime errors.
  7. Synthesize. When the plan finishes, a final LLM call produces a polished answer in <final> tags.

Writing a new tool

Subclass BaseTool in app/tool/base.py and register it with SessionManager:

from app.tool.base import BaseTool, ToolResult

class MyTool(BaseTool):
    name = "my_tool"
    description = "what it does"

    async def execute(self, **kwargs) -> ToolResult:
        ...
        return ToolResult(success=True, output_text="...", output_data={...})

The planner prompt in app/prompt/master_planner_prompts.py needs a matching schema entry so the LLM knows how to call it.

Configuration

See .env.example for all supported variables. Key ones:

Variable Purpose Default
E2B_API_KEY sandbox auth (required)
E2B_TEMPLATE_ID sandbox base image base
LLM_PROVIDER google | anthropic | openai | deepseek google
GOOGLE_API_KEY Gemini key
GEMINI_MODEL_NAME model id gemini-2.0-flash
PLAN_WORKSPACES_DIR local mirror root output_workspaces
LOG_LEVEL logger verbosity INFO

Status

This is a small, readable reference implementation — not a production framework. The pieces that are real and wired up:

  • Planning loop, tool executor, context summarization, recovery
  • Terminal + Python tools with sandboxed execution
  • CLI front-end

The pieces that are intentionally thin:

  • server.py is a placeholder; wire it to FastAPI yourself if you need HTTP/WS
  • The non-Gemini LLM clients are scaffolded but may need finishing for your model of choice

License

MIT.

About

A minimal, readable ReAct-style planning agent that plans, executes tools in an E2B sandbox, observes results, and self-heals on failure.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages