TL;DR
You hand context_packet a one-line task ("debug
why manager onboarding role checks are failing"). You get back a
structured packet: the most likely files, the routes touching
them, the active findings on those files, the database objects
they reference, scoped instructions from
.mako/instructions.md, and a recommendation for what
to read next. The agent starts there instead of grepping its way
in.
The problem this solves
An AI coding agent without persistent context starts every turn from zero. The first thing it does is explore: walk directories, grep for likely strings, read files, re-read files, guess at imports. This burns tokens — typically 5,000 to 15,000 per turn — before any actual code work begins.
Most of that exploration is wasted. The agent reads the same files repeatedly across turns. It misses the database schema because it doesn't know to look at it. It hallucinates routes because it pattern-matches from training data instead of looking at the real router.
A context packet collapses that whole opening sequence into one tool call.
The shape of a context packet
Every context packet has the same fields. Names match the actual MCP tool output:
{ "primaryContext": [ { "path": "app/dashboard/manager/layout.tsx", "reason": "manager-scoped layout — likely role check site", "score": 0.91 }, { "path": "lib/auth/dal.ts", "reason": "role resolution", "score": 0.87 } ], "relatedContext": [ { "path": "lib/auth/roles.ts", "score": 0.62 } ], "activeFindings": [ { "code": "auth/missing-tenant-scope", "path": "lib/auth/dal.ts", "line": 142, "severity": "warn" } ], "risks": [ "This file touches admin_audit_log — RLS-sensitive." ], "scopedInstructions": [ { "file": ".mako/instructions.md#auth", "text": "..." } ], "recommendedHarnessPattern": "read primaryContext → call file_findings → edit", "expandableTools": ["route_trace", "db_rls", "reef_inspect"] }
Each section has a clear purpose:
primaryContext— top-ranked files. Read these first.relatedContext— second-tier files that may matter once you've read the primary set.activeFindings— durable findings on those files (lint/audit issues, design rules violations, prior reviews).risks— short risk callouts ("this touches RLS-sensitive tables").scopedInstructions— relevant slices of.mako/instructions.md/AGENTS.mdfor these files.recommendedHarnessPattern— literal next-tool suggestion, like a recipe.expandableTools— other Mako tools that would be useful next.
How agentmako produces them
The packet is composed from the local SQLite index and the Reef Engine, not from a model. Inputs:
- Symbol/file/route/import index, refreshed on demand.
- Postgres or Supabase schema snapshot (when configured).
- Reef facts and findings — durable across sessions.
- Recently-edited files (working tree overlay).
- Scoped instructions in
.mako/instructions.md.
The ranking is deterministic. Same request + same index state + same findings = same packet. No embedding noise, no temperature knob.
You can shape the packet at call time:
{ "request": "review auth impact of this change", "focusFiles": ["lib/auth/dal.ts", "app/dashboard/manager/layout.tsx"], "includeInstructions": true, "includeRisks": true, "freshnessPolicy": "prefer_fresh", "budgetTokens": 4000 }
Why "deterministic" matters
If your context engine is probabilistic, the agent gets different answers for the same question. That makes regressions hard to reason about — was the bad output from the model, or from a different shuffle of retrieved chunks?
A deterministic packet means the agent's behavior is a function of the index state. When the index is fresh, the packet is correct. When the index is stale, the packet is labeled stale (see freshness). You can replay the same call and reason about what changed.
Context packets vs. RAG / vector search
RAG retrieval treats code as text and looks for semantically similar chunks. That works for unstructured documents but loses the structure code already has — file paths, types, imports, route definitions, foreign keys.
A context packet uses that structure directly. "Find the
handler for /api/manager/onboarding" is a graph
query, not a similarity search. The handler resolves through the
route table, then the import graph, then symbol references — all
deterministic.
Embeddings are still useful in some places (e.g. ranking fuzzy "what about this" follow-ups), but the spine of a Mako packet is the typed graph.
How files get ranked
The score on each primaryContext entry is a
weighted combination of deterministic signals — not a model
inference. Roughly:
- Direct match — the request mentions a symbol, route, file, or table that resolves through the index to this file.
- Graph proximity — files reachable in one or two hops through imports, route handlers, or schema references from the directly-matched file.
- Recent edits — files touched in the current working tree get a small boost. The agent is usually working on something nearby.
- Convention match — files that match
project-wide conventions surfaced by
project_conventions(auth guards, route patterns). - Reef weight — files with active findings or recent diagnostic runs rank higher; the agent should know about them.
The budgetTokens input caps the total token
weight of returned files. Mako trims from the bottom of the
ranked list until the budget fits.
Context packets in practice
The opening call
For any vague task, start with one
context_packet. The agent reads the
primaryContext files first, then optionally calls
file_findings on each before editing. This single
call replaces 5–10 grep/file-walk turns.
Focused review
When you already know the files involved, pass them via
focusFiles. Mako keeps the same packet shape but
biases ranking toward those files and their immediate
neighborhood — useful for targeted code review.
Pre-edit risk check
Set includeRisks: true. If the file touches
tenant-keyed tables, RLS-sensitive routes, or auth boundaries,
the packet flags it before the agent edits. Cheap to ask;
expensive to ignore.
What context packets are not
- Not the source of truth. The packet points the agent at files. The files themselves are still the truth — read them.
- Not infinite. The
budgetTokenssetting is real. Asking for "the whole codebase" returns the top-ranked slice, not everything. - Not always fresh. The packet's freshness
is the freshness of the underlying index. After edits, prefer
live_text_searchfor exact line numbers. - Not a write surface.
context_packetis read-only. The agent edits via its normal file-edit tools after reading the packet.
Common pitfalls
- Skipping the packet on follow-ups.
After 5–10 turns the agent's working memory drifts. Re-call
context_packetwith a fresh request; ranking shifts as edits land. - Asking too broadly. "Help me with this
project" produces a generic packet. "Trace why
/api/xreturns 403 for some users" produces a targeted one. - Trusting line numbers from a stale index.
The packet's
linefields are as current as the index. After heavy edits, refresh first or uselive_text_searchfor line-accurate work. - Ignoring
activeFindings. They're the cheapest signal in the packet. If a finding on the file mentions exactly the bug you're chasing, you're done thinking — start there.