ExecutionAgent Documentation¶
ExecutionAgent is URSA's execution-focused agent for carrying out concrete tasks in a workspace. It can write files, edit code, read artifacts, download data, execute safe shell commands, and use optional search/RAG/MCP tools. Current implementations also include a structured review-until-complete loop before the final recap.
Use ExecutionAgent when the request is action-oriented: create or modify files, run code, inspect command output, perform analyses, or assemble artifacts. Use ChatAgent for lighter conversational assistance with tools.
Basic usage¶
from langchain.chat_models import init_chat_model
from ursa.agents import ExecutionAgent
llm = init_chat_model("openai:gpt-5.4-mini")
agent = ExecutionAgent(llm=llm, workspace="analysis_workspace")
state = agent.invoke("Write and execute a Python script to print the first 10 integers.")
print(agent.format_result(state))
The returned state contains the conversation/tool transcript in state["messages"] and the final recap as the last message.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
llm |
BaseChatModel |
required | Language model used for execution, review, and recap. |
log_state |
bool |
False |
Write debug state to execution_agent.json. |
extra_tools |
list[BaseTool] \| None |
None |
Additional LangChain tools to bind. |
tokens_before_summarize |
int |
50000 |
Token budget before message context is summarized/compacted. |
messages_to_keep |
int |
20 |
Number of recent messages to preserve during context compaction. |
use_web |
bool |
False |
Add web, OSTI, and arXiv search tools. |
safe_codes |
list[str] \| None |
['python', 'julia'] |
Interpreters/languages treated as safe command contexts by the command-safety machinery. |
**kwargs |
dict |
{} |
Passed to BaseAgent / AgentWithTools, including workspace, persistence, groups, RAG tools, MCP, and checkpoint options. |
Default tools¶
The default execution tool set includes:
run_command— execute shell commands in the workspace with safety review.write_code— write new files.edit_code— edit existing files.read_file— read files, including PDF text extraction support.download_file_tool— download files from URLs.read_image_tool— load images.list_experiences— list durable Markdown experience files.read_experience— read an experience file.write_experience— write or append an experience file.edit_experience— edit an experience file.
When use_web=True, the agent also receives:
run_web_searchrun_osti_searchrun_arxiv_search
You can add custom tools through extra_tools, persistent RAG tools through rag_tools, or MCP tools through the CLI/MCP configuration.
Review-until-complete workflow¶
ExecutionAgent compiles a LangGraph state machine with four main nodes:
agent— the executor LLM decides what to do next and may request tool calls.action— executes requested tools.review— asks the LLM for a structured completeness assessment.recap— produces the final concise summary returned to the user.
The current loop is:
- The executor receives the user request and current message context.
- If it requests tool calls, the
actionnode executes them. - Tool results return to the executor for the next step.
- When the executor emits an ordinary assistant response with no tool calls, the graph routes to
reviewrather than finishing immediately. - The review node evaluates whether the work adequately addresses the original user request.
- If the review says the work is incomplete, the review rationale is appended as a new human feedback message and the graph loops back to
agent. - If the review says the work is complete, the graph proceeds to
recapand finishes.
The structured review object is represented as:
class ReviewAssessment(BaseModel):
is_complete: bool
reason: str
The graph stores this value in state["review"]. Incomplete reviews intentionally drive further work, so the agent can recover from premature “done” responses.
State model¶
ExecutionState includes these key fields:
messages— ordered system, human, AI, and tool messages.symlinkdir— optional symlink metadata for exposing external directories inside the workspace.review— optionalReviewAssessmentfrom the structured review node.
The last message after a successful invocation is the recap. agent.format_result(state) returns that message text.
Custom tools¶
from math import sqrt
from langchain.tools import tool
from langchain.chat_models import init_chat_model
from ursa.agents import ExecutionAgent
@tool
def hypotenuse(a: int, b: int) -> float:
"""Compute sqrt(a**2 + b**2)."""
return sqrt(a**2 + b**2)
llm = init_chat_model("openai:gpt-5.4-mini")
agent = ExecutionAgent(llm=llm, extra_tools=[hypotenuse])
state = agent.invoke("Use the hypotenuse tool for a=3 and b=4.")
print(agent.format_result(state))
Workspace and safety notes¶
- Files are written to and commands run from the configured workspace.
- Use a dedicated workspace for agent-driven execution.
- Shell command execution is safety-gated and unsafe command/tool results can be surfaced back to the graph.
- Web/search tools are opt-in with
use_web=Trueorursa --use-webin the CLI. - Long transcripts are compacted using the shared message-context preparation helpers according to the configured token and message limits.