MetaAgent is the engine of self-improvement. Its only job is to look at the current state of the codebase and the scores from previous generations, then decide what to change. The changes it makes are what the next generation’s TaskAgent inherits.
Class Definition
meta_agent.py
MetaAgent extends AgentSystem, which provides:
self.model— the LLM identifier (defaults toOPENAI_MODEL = "openai/gpt-4o").self.log— a thread-safe logger backed byThreadLoggerManagerthat writes to a markdown chat-history file.
What forward() Does
forward() constructs a single instruction string and hands it to chat_with_agent. The function signature is:
| Parameter | Type | Description |
|---|---|---|
repo_path | str | Absolute path to the repository root inside the Docker container (e.g. /HyperAgents/) |
eval_path | str | Path containing prior generations’ evaluation results; the meta-agent reads scores from here |
iterations_left | int | None | Number of future meta-agent invocations remaining; passed so the agent can plan horizon-aware changes |
"Modify any part of the codebase at ." — so that the meta-agent has maximum freedom to decide what to change: it may edit task_agent.py, introduce helper modules, change prompts, or even modify its own loop logic.
eval_path is passed to the meta-agent as context via the instruction string that run_meta_agent.py builds, not directly inside MetaAgent.forward. The forward method itself only surfaces repo_path in the instruction, while run_meta_agent.py passes eval_path as --evals_folder and the meta-agent can access it via bash tools.Tools Available to the Meta-Agent
chat_with_agent is called with tools_available='all', which loads every module in agent/tools/. Two tools are currently available:
- bash
- editor
Defined in Key characteristics:
agent/tools/bash.py. Runs arbitrary shell commands in a persistent BashSession.- State is persistent across calls within a single
forward()invocation (same bash process). - 120-second timeout per command.
- No internet access inside the Docker sandbox.
- Supports background processes (
sleep 10 &) andapt/pipinstalls via local mirrors.
<json>...</json> tags. The loop in chat_with_agent continues calling the LLM until no tool call is found in the response, or until max_tool_calls=40 is reached.
Model Defaults and Overrides
AgentSystem.__init__ sets self.model from agent/llm.py:
agent/base_agent.py
run_meta_agent.py overrides this base default: its --model argument defaults to CLAUDE_MODEL = "anthropic/claude-sonnet-4-5-20250929". In practice, when the meta-agent is invoked via generate_loop.py, the effective default model is Claude unless --model is explicitly passed.agent/llm.py:
agent/llm.py
generate_loop CLI passes --model through to run_meta_agent.py, which passes it to the MetaAgent constructor.
How run_meta_agent.py Invokes MetaAgent
run_meta_agent.py is the entry point called inside the Docker container:
run_meta_agent.py
Run the meta-agent
MetaAgent.forward() is called. The LLM uses bash and editor tools freely for up to 6 hours (container timeout).Reset domain code
reset_paths_to_commit(paths=["domains/"]) uses git checkout to undo any changes the meta-agent made inside domains/. This keeps the evaluation harness stable across generations.Compilation Check
Afterrun_meta_agent.py exits, generate_loop.py runs a quick sanity check before proceeding to evaluation:
utils/gl_utils.py (run_commands_to_check_compilation)
RuntimeError is raised and the generation is marked as having no valid evaluation result.
Task-Agent
What the meta-agent is ultimately trying to improve.
Evolution Loop
How the generate loop orchestrates meta-agent invocations.