| name | extend-agent |
| description | User-driven loop to change the context agent (or any agent in this repo) — add a source/tool/MCP server, add a capability (knowledge base, memory, sub-agent, scheduled task), refine its instructions, or fix a specific known bug, verifying each change against the live container. Use whenever the user names a concrete change ("add a Google Drive source", "make the daily rundown include the calendar", "the agent keeps doing Y, fix it"). For autonomous hardening with no specific change in mind use improve-agent. |
Extend an Agent
Coding-agent workflow — a /slash-command your coding agent (Claude Code, Codex, …) runs while developing this repo. Not a runtime skill the deployed @context agent runs; those live in skills/.
You are recursively extending a target agent with the user in the driver's seat. Each iteration: the user names a change, you implement it with an Agno-aware eye (using the agno-docs MCP for any toolkit / API research), the change is verified against the live agent, then you ask if there's more to do. Stop when the user says they're done.
This is the user-driven half of the iteration loop. The autonomous half lives in the improve-agent skill — Claude derives probes from the agent's INSTRUCTIONS and hardens behavior with no user input. Use this skill to change the agent (add tools, add capabilities, refine the prompt, fix a known bug). Run improve-agent afterward to confirm nothing else regressed.
The platform is on http://localhost:8000 with hot-reload enabled (RUNTIME_ENV=dev), so edits to agents/<slug>.py are picked up by uvicorn within ~1s. Edits to app/main.py (e.g. registering a new sub-agent) require a container restart — Step 5 covers this.
0. Preconditions
-
Live container reachable: curl -sSf http://localhost:8000/health returns 200. If not, ask the user to docker compose up -d --build first. (docker compose ps is unreliable from worktrees or alternate clones — trust the health probe.)
-
Live container is bound to this checkout — otherwise hot-reload won't see your edits:
docker inspect context-api --format '{{range .Mounts}}{{.Source}}{{"\n"}}{{end}}' | grep -F "$(pwd)"
Empty result = the container's /app is bound to a different repo path. Either cd to that repo or restart the container from this directory (docker compose down && docker compose up -d --build).
-
Ask the user for the target agent slug (usually context — the one registered agent).
-
Recommend the user create a feature branch (git checkout -b extend/<slug>-$(date +%Y%m%d)) so any wrong turns are easy to revert.
1. Read the agent first
Open agents/<slug>.py. Capture:
- Stated purpose — the file's docstring + the
INSTRUCTIONS string.
- Tools — what's wired and what each one does.
- Pattern — deterministic function tools registered straight on the agent (like the queue tools in
agents/inbox.py) or a context provider — a sub-agent behind query_<id> / update_<id> tools, built by a _create_<id>_provider() factory in agents/sources.py.
- Existing levers —
learning= (the LearningMachine and its store modes), num_history_runs, knowledge=, model id.
Restate the agent's purpose to the user in 1-2 sentences before asking what to change. This catches "I thought it did X but actually it does Y" upfront.
2. Ask what to improve
Use the AskUserQuestion tool with these branches (multi-select allowed if the user wants multiple changes in one pass — handle them sequentially in Steps 3-6, then loop):
- Add a tool — new MCP server, agno toolkit, or function tool.
- Add a capability — knowledge base (RAG), memory tweak, sub-agent / context provider, scheduled task.
- Refine instructions — clarify a rule, narrow scope, change tone, change format.
- Fix a bug — user has a specific failing prompt or wrong behavior in mind.
- Something else — free-form; let the user describe.
If the user picked "Fix a bug" or "Something else," ask a follow-up free-form question for the specifics (the failing prompt, the observed behavior, what they want instead).
3. Ground the change in agno docs
For any change touching agno surface area — toolkit imports, knowledge config, memory flags, scheduler, sub-agent patterns — search the agno-docs MCP (configured in .mcp.json) before writing code. Fall back to fetching https://docs.agno.com/llms.txt only if the MCP is unavailable.
What to capture per branch (stacking multiple changes in one session? run the agno-docs lookups in parallel):
- Add a tool — import path (e.g.
from agno.tools.exa import ExaTools), constructor args that matter for this agent, required env vars, pip dependencies. The toolkit's Prerequisites section lists deps and auth.
- Add a capability:
- Knowledge base — build an agno
Knowledge with a PgVector vector db (db_url from db.url), pass via knowledge= on the Agent. Document load step (.add_content_async()) goes wherever ingestion lives.
- Memory / learning — the
learning=LearningMachine(...) on the Agent constructor (per-store configs and LearningModes — note the shared-scope stores entity_memory / learned_knowledge / decision_log inject context for every caller, so they must not be enabled on this agent; see docs/SECURITY.md), plus add_history_to_context, num_history_runs. Read agno's learning docs to pick the right store and mode.
- Source / context provider — mirror a
_create_<id>_provider() factory in agents/sources.py and add it to create_context_providers() (env-gated providers go through the try/except loop). The main agent sees query_<id> (and update_<id> if writable); the sub-agent does the work.
- Scheduled task — see agno scheduler docs and the
scheduler=True line in app/main.py.
- Refine instructions — no docs needed. Read the current
INSTRUCTIONS, propose a minimal diff. Prefer narrowing ("on recent-events questions, follow up with a web_fetch") over forbidding.
- Fix a bug — first reproduce the failure on the live agent (see Step 6). Then identify the layer:
INSTRUCTIONS (most common), tool (wrong tool wired or missing), model (under-capable), env (rate limit, missing key, MCP unreachable).
Don't guess any of these. If the agno-docs MCP returns nothing for a name the user gave (e.g. an MCP server they want to wire), tell them; offer to use generic MCPTools(url=..., transport=...) and ask for the URL.
4. Propose, then edit
Before editing, tell the user in 2-3 lines what you're about to change and why. Get a quick "yes" — most missteps come from misunderstanding the ask, not bad code.
Then edit. Files in scope:
Keep edits surgical. One change per iteration of this loop — if the user asked for three things, do them one at a time so each can be smoke-tested independently.
5. Reload
-
Edited only agents/<slug>.py, app/config.yaml, or other files inside agents/ / app/ — uvicorn picks it up in ~1s. No restart.
-
Edited app/main.py (registered a sub-agent, changed interfaces) — restart:
docker compose restart context-api
-
Added pip deps in pyproject.toml — regenerate the lockfile and rebuild:
./scripts/generate_requirements.sh
docker compose up -d --build
After a restart or rebuild, poll /health until the API is back:
until curl -sSf http://localhost:8000/health > /dev/null; do sleep 0.5; done
For hot-reload, confirm the edit reached the container before smoke-testing:
docker exec context-api grep -c "<unique substring from your edit>" /app/agents/<slug>.py
0 means the file in the container hasn't changed — almost always a bind-mount mismatch. Step 0 catches this earlier.
6. Smoke test the change
Pick a prompt that exercises the change you just made. For "Add a tool," the prompt should force the new tool to fire. For "Fix a bug," reuse the failing prompt the user described. For "Refine instructions," pick a prompt the rule was meant to handle.
curl -sS -X POST http://localhost:8000/agents/<slug>/runs \
-F "message=<the targeted prompt>" \
-F "user_id=claude-extend-agent" \
-F "stream=false" \
-o /tmp/improve-out.json \
-w "HTTP %{http_code} in %{time_total}s\n"
jq -r '.content // .' < /tmp/improve-out.json
Read tool calls from the container logs to confirm the right tool fired:
docker logs context-api --since 30s 2>&1 | grep -E "Running: \w+\(" | head -40
(Running: <tool>( is the line shape agno emits per tool call when AGNO_DEBUG=True, which compose sets for dev.)
Show the user the response and the tool calls. Did the change land?
- Yes — go to Step 7.
- Almost — one more edit pass. Iterate at most 2-3 times before stopping and asking the user how they want to proceed (revert, try a different approach, accept and move on).
- No / made it worse — surface what happened. Offer to revert (
git checkout agents/<slug>.py) before trying again.
7. Loop or wrap up
Ask the user (free-form): "Anything else to improve, or are we done?"
- More to do — go back to Step 2.
- Done — Step 8.
The recursion is the point: each iteration is one small, verified change. Drift shows up faster when changes are small and tested in isolation.
8. Report
Summarize for the user:
- One line per accepted change (which lever, what changed).
git diff --stat plus a short git diff block for the agent file.
- Suggested commit message —
feat(<slug>): <one-line> for new tools/capabilities, fix(<slug>): <one-line> for bug fixes, chore(<slug>): refine instructions for prompt-only edits. Combine if multiple types in one session.
- Recommended next step — run the
improve-agent skill to autonomously verify the agent still does what its INSTRUCTIONS say it does. The change you just made widened the agent's surface area; the autonomous loop catches anything that regressed.
A simple change (one tool, one prompt refinement) takes 5-10 minutes. A capability addition (knowledge base, sub-agent) usually 15-30. The loop scales linearly with how many changes the user wants to stack into one session — keep them small and verifiable.
Worked example
Target: context. The user wants @context to also read their Google Drive.
Step 2 — user picks "Add a capability" (a new source / context provider).
Step 3 — search the agno-docs MCP for the gdrive context provider. Capture the import path, constructor args, required env vars / auth, and any pip deps.
Step 4 — propose: "Add an env-gated gdrive source: a _create_gdrive_provider() factory in agents/sources.py, wired through the try/except loop in create_context_providers() so a bad credential can't take the registry down. Document the env vars in example.env. Add a quick prompt that exercises it." User says yes.
Edit agents/sources.py (factory + registry — the provider exposes query_gdrive to the agent automatically; no change to context.py). Add the env vars to example.env. Add a quick prompt to app/config.yaml:
context:
- "What's in my Q3 planning doc?"
Step 5 — pip deps changed? ./scripts/generate_requirements.sh && docker compose up -d --build; otherwise hot-reload picks up agents/ edits in ~1s. Poll /health.
Step 6 — cURL the context agent with the quick prompt. Logs show Running: query_gdrive(. Response is grounded in the doc.
Step 7 — user says "no, that's it."
Step 8 — diff summary, commit feat(context): add gdrive source, recommend improve-agent to harden the broader behavior.
That's the loop. Most sessions are smaller — one tool, one rule, one bug.