# Context-budget receipts Privacy-safe receipts for answering a narrow operational question: > What ate the agent's context before or after the task? This is different from generic token accounting. A context-budget receipt should prove which context surfaces were available, which ones crossed the boundary, which ones stayed deferred or suppressed, and how much budget remained — without exporting raw prompts, tool schemas, tool outputs, memory bodies, file paths, ticket text, secrets, or customer data. If you want a copyable Agent Skill recipe instead of a spec-style guide, see [`skills/context-receipts/`](../skills/context-receipts/). It turns the receipt pattern into a 60-second smoke checklist for Tool Search, skills, and subagent boundaries. ## If Tool Search already fixed the bloat Modern hosts can defer large MCP catalogs behind Tool Search or similar lazy discovery. That changes the receipt question; it does not remove it. Do not use a context-budget receipt to re-prove that every schema was smaller than before. Use it to prove the boundary that lazy loading promised: - the catalog/index was loaded instead of full definitions; - the selected query loaded only the matching tool definitions; - unselected tool groups stayed deferred or withheld; - a schema did not enter a side lane such as `messages`, subagent bootstrap, skill preamble, or memory hydration; and - the receipt records what evidence is missing when only fallback client telemetry exists. This makes the receipt useful in the common objection case: "MCP context bloat is solved by Tool Search." A good receipt should answer: **solved where, for this turn, through which lane, and with what proof?** Runnable fixture for the normal happy path: ```bash node examples/context-input-evidence/convert-mcp-tool-search-log.mjs ``` Public trace: - `examples/context-input-evidence/mcp-tool-search-otel-trace.json` Minimum hidden-bypass fields for managed seats or gateways: ```json { "event.name": "mcp.deferral.evaluated", "mcp.defer_loading.enabled": true, "mcp.catalog.deferred": true, "mcp.tool_search.selected_tool_count": 0, "context.messages.remote_mcp_schema_count_bucket": "over_25", "context.messages.delta_token_bucket": "under_100k", "context.attribution": "remote_mcp_schema_in_messages", "expected_behavior": "deferred_until_tool_search_match", "verdict": "deferral_bypassed", "privacy.raw_schema_included": false } ``` That shape deliberately avoids raw schema bodies, connector names, private URLs, and prompt text. It proves attribution, not whether the selected tool was semantically optimal. ## When to use this receipt Use a context-budget receipt when a coding agent looks lazy, fails with `prompt is too long`, or returns a tiny summary after a subagent/tool-heavy step and you need to distinguish: - the user prompt was too large; - MCP/tool schemas were eagerly materialized; - a skill or rule listing consumed startup budget; - memory/search results hydrated too much context; - a manager subagent isolated heavy tools correctly; - a child subagent pasted raw tool output back into the parent; or - a CLI/MCP gateway used progressive disclosure correctly. ## Minimum contract A useful receipt starts small: ```json { "event.name": "context.budget.evaluated", "component": "subagent_boot | mcp_gateway | cli | mcp_manager | delegation", "candidate_count": 566, "loaded_count": 2, "suppressed_count": 564, "delivered_hash_count": 2, "startup_token_bucket": "100k-200k", "remaining_token_bucket": "0-10k", "privacy.raw_prompt_included": false, "privacy.raw_schema_included": false, "privacy.raw_tool_output_included": false, "audit_gap": "proves context boundary, not semantic quality" } ``` Keep exact counts when they are not sensitive. Bucket token counts and sizes when exact values could reveal private workload shape. ## Code-search / retrieval receipts Semantic code-search MCPs and RAG-over-repo tools can reduce context bloat by returning only relevant chunks. The observability gap is that retrieval and agent-loading are two different boundaries: a tool may return five chunks, a client may dedupe or stale-filter two of them, and only three may actually enter the agent context. The receipt should prove: - the indexed snapshot/version used, without raw local paths or embedding secrets; - the search request identity/category, without raw query text or filters; - returned result identities, ranks, score buckets, stale/duplicate markers, and path hashes/extensions/range buckets; - which returned chunks were loaded into agent context versus suppressed by the client/harness; and - raw code, private paths, prompts, customer names, URLs, tokens, and ticket text stayed out of the receipt. Runnable fixture: ```bash node examples/context-input-evidence/convert-code-search-retrieval-log.mjs ``` Public trace: - `examples/context-input-evidence/code-search-retrieval-otel-trace.json` ## Post-hoc pruning / context cleaning Context-cleaning tools can reduce a bloated session after context has already entered the transcript. That creates a separate proof boundary from lazy loading: what was pruned, minified, stubbed, deduped, protected, and backed up? The receipt should prove: - prescription/mode/trigger without raw session JSONL; - before/after token and byte buckets; - per-strategy candidate, changed, removed, and protected buckets; - compact summaries, behavioral digests, active task state, and other protected items were not removed; - a backup was created/verified for executed runs; and - raw tool output, file contents, session text, emails, secrets, paths, and customer data stayed out of the receipt. Runnable fixture: ```bash node examples/context-input-evidence/convert-pruning-log.mjs ``` Public trace: - `examples/context-input-evidence/pruning-otel-trace.json` ## Compaction transaction / rollback A failed `/compact` is not just a bad summary. It can leave several state surfaces disagreeing: prior context, candidate summary, deferred-tool registry, system-reminder replay queue, local command output, and post-token metadata. The receipt should prove whether compaction committed a new authoritative state or rolled back cleanly. The receipt should prove: - summary call status and duration bucket; - whether a candidate summary was available/validated; - `swap_committed` and `original_context_preserved`; - backup availability; - deferred-tool registry and system-reminder queue restoration; - replayed stale reminder count stayed zero on rollback; - `post_tokens_recorded_as_success` stayed false on failure; and - raw transcript, tool output, private paths, errors, secrets, and summary text stayed out of the receipt. Runnable fixture: ```bash node examples/context-input-evidence/convert-compaction-transaction-log.mjs ``` Public trace: - `examples/context-input-evidence/compaction-transaction-otel-trace.json` ## Subagent boot budget Subagents can fail before task #1 if they inherit every MCP schema, skill listing, rule, or memory index from the parent. The receipt should separate: - `available` — what could have been loaded; - `loaded` — what actually entered the subagent prompt/context; - `suppressed` or `deferred` — what stayed out; - `remaining` — coarse budget after bootstrap; and - `failure_or_headroom` — whether the subagent had room for tool results. Runnable fixture: ```bash node examples/context-input-evidence/convert-subagent-context-budget-log.mjs ``` Public trace: - `examples/context-input-evidence/subagent-context-budget-otel-trace.json` ## Per-agent MCP injection Role-specific subagents may need different MCP surfaces: a testing agent might need `testing` and `github`, while deployment, analytics, email, or browser servers should stay outside that boot context. The receipt should prove the policy boundary before the first task: - role/session id for the subagent without raw instructions; - available server count/hash for the role; - excluded server count/hash before boot; - loaded vs deferred tool-definition counts; - startup token bucket after the policy was applied; and - an explicit audit gap that this proves injection scope, not semantic tool quality. Minimal events: - `subagent.mcp_policy.applied` - `subagent.context_boot.evaluated` ## ToolSearch propagation into subagents When MCP tools are deferred behind `ToolSearch`, subagent bugs can hide in three different layers: - the parent/orchestrator policy intended to expose or exclude MCP/ToolSearch; - the subagent `tools:` declaration made `ToolSearch` available, stripped it, or froze an older registry; and - the runtime filter actually exposed the deferred-tools channel after spawn. The receipt should make those layers distinguishable without raw tool schemas, prompts, agent files, or private paths. It should include: - spawn path and whether skill context was active; - coarse bucket for parent intermediate tool calls before spawn; - `tools:` declaration shape such as wildcard, explicit include, or exclusion style; - whether `ToolSearch` was declared and actually exposed to the subagent; - parent vs subagent MCP server count buckets; - loaded vs deferred tool-definition buckets; and - a `filtered_by` or `filter_reason` category. Runnable fixture: ```bash node examples/context-input-evidence/convert-subagent-toolsearch-propagation-log.mjs ``` Public trace: - `examples/context-input-evidence/subagent-toolsearch-propagation-otel-trace.json` ## Delegation boundary A subagent can save parent context at boot and still lose the benefit if raw child output is pasted back into the parent. The receipt should prove: - delegation happened; - child output size stayed in the child/subagent store; - parent received a bounded summary, not raw output; - raw child output was not copied into the receipt; and - the audit gap remains explicit: the receipt proves the boundary, not summary correctness. Runnable fixture: ```bash node examples/context-input-evidence/convert-subagent-delegation-log.mjs ``` Public trace: - `examples/context-input-evidence/subagent-delegation-otel-trace.json` ## MCP manager isolation When a manager subagent owns hundreds of MCP tools, the parent should see a small request/summary surface, not the whole tool catalog. The receipt should prove: - parent full schemas were not loaded; - the manager booted with the tool catalog; - one or a small set of tools was selected; - unselected schemas stayed suppressed; and - only a bounded parent summary returned. Runnable fixture: ```bash node examples/context-input-evidence/convert-claudekit-mcp-manager-log.mjs ``` Public trace: - `examples/context-input-evidence/claudekit-mcp-manager-otel-trace.json` ## Progressive disclosure: MCP gateway or CLI If a gateway or CLI avoids context bloat by showing an index/prompt first and expanding one schema/help page later, the receipt should prove the disclosure boundary: - small agent prompt or meta-tool/index loaded at startup; - full schemas/specs were not loaded at startup; - one command/schema was hydrated on demand; - raw args/results stayed out of the receipt; and - selected/suppressed counts are visible enough for debugging. Runnable fixtures: ```bash node examples/context-input-evidence/convert-agentgateway-progressive-disclosure-log.mjs node examples/context-input-evidence/convert-cli-progressive-disclosure-log.mjs node examples/context-input-evidence/convert-mcp-tool-search-log.mjs ``` Public traces: - `examples/context-input-evidence/agentgateway-progressive-disclosure-otel-trace.json` - `examples/context-input-evidence/cli-progressive-disclosure-otel-trace.json` - `examples/context-input-evidence/mcp-tool-search-otel-trace.json` ## Privacy defaults For shareable receipts: - hash or HMAC stable identifiers; prefer HMAC for predictable IDs, paths, user IDs, and audit IDs; - fail closed or omit identifier hashes when the HMAC key is missing; - bucket large sizes and token counts; - never export raw schemas, raw memory, raw prompt, raw tool output, paths, tickets, emails, secrets, or customer-specific strings; - include explicit `raw_*_included=false` flags; and - include `audit_gap` so readers do not confuse boundary evidence with semantic correctness. ## What to ask in a bug report Instead of “why is my subagent bad?”, ask for a receipt or debug JSON that can answer: 1. How many tools/skills/rules/memory entries were available? 2. How many were loaded into the parent? 3. How many were loaded into the subagent? 4. How many were suppressed/deferred? 5. For a subagent, which MCP servers were allowed and which were excluded before boot? 6. What token bucket remained before the first tool call? 7. Did raw child output return to the parent, or only a bounded summary? That is the narrow wedge for Pluribus: context-budget evidence across agent boundaries, not another memory store or tool router.