Skip to content

feat(context): stateful compact serving for agent context tools#869

Open
edwin-zvs wants to merge 1 commit into
mainfrom
feat/context-serve-state
Open

feat(context): stateful compact serving for agent context tools#869
edwin-zvs wants to merge 1 commit into
mainfrom
feat/context-serve-state

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Problem

Input-token efficiency review of construct_context / agentd_context found five gaps (the etag work in #865 only landed on the MCP path):

  1. Smith's native agentd_context bypassed all compaction — it pretty-printed the full AgentdContext on every call: 17-bullet memory policy + 13-bullet widget policy (~5KB), the full 12-entry Markdown-extension registry (~6KB), full memory files, and the full program-run payload. Roughly 3k tokens of static text per call before any real content, on the harness that calls the tool most.
  2. Monolithic program-run etag — computed over the whole struct, so any program edit (including the mandatory first status-only shimmer edit) resent ~4KB of static run instructions + smart-clip reference along with the markdown.
  3. Memory resent after the agent's own edits — the agent can't compute the server-side FNV etag, so right after writing a memory file it got the full content back.
  4. Dedup relied on the model echoing known_* etags — unenforced and unmeasured.
  5. Static repeatsinstructions, session_widgets, and the reference hint were resent on every call.

Change

One shared compact-serving layer in construct_protocol::agent_context, used by both construct-mcp and smith's native tool:

  • Per-process serve state: the serving process (one process = one agent) remembers what it sent. Repeat calls collapse unchanged memory/program payloads to {path, etag, unchanged} markers and send static fields once. known_* echoes are still honored (covers a restarted serving process mid-conversation).
  • Split program-run etags: markdown and the static run reference (instructions + smart clips) are tracked independently — a program edit resends only the markdown. Status-only shimmer edits don't change markdown, so the required planning pass now costs ~nothing on the next context call.
  • skip_memory: true: omit memory content the agent already holds verbatim (e.g. it just wrote the files); paths + etags still returned, and the content is marked served.
  • refresh: true — the compaction escape hatch: resends everything. Everything omitted stays disk-recoverable (memory by path, program via construct_program_get), so a stale serve state degrades to an extra fetch, never data loss.
  • Smith resets serve state natively on auto-compact, manual /compact, and destructive prune — the exact moments the model loses served content — closing the compaction/etag hazard on the native side entirely.
  • Dropped known_* from the tool schema (still accepted), trimmed truncated/remaining_bytes to truncation cases only.

Not done (deliberate): version-based markdown diffs for program runs — partial markdown risks the agent forming a wrong mental model of the document; the etag split captures nearly all the win.

Spec 0095 updated with the serving contract (identical behavior across surfaces; native tools must not bypass the budget layer).

Testing

  • New unit tests for the shared layer (first-serve/repeat-serve, refresh, split etags, skip_memory, known-etag echo, include_reference) in construct_protocol::agent_context.
  • MCP dispatcher wiring test updated to exercise the process-level state.
  • Full cargo test --workspace: all 19 targets green.

🤖 Generated with Claude Code

The construct_context / agentd_context payload is now deduplicated per
serving process instead of relying on the model to echo etags back:

- Shared compact layer in construct_protocol::agent_context, used by both
  construct-mcp and smith's native tool. Smith previously bypassed all
  compaction and pretty-printed the full context (policies, extension
  registry, full memory, full program run) on every call.
- The serving process remembers what it sent: repeat calls collapse
  unchanged memory/program content to etag markers and send static fields
  (instructions, widget paths, reference hint) once. known_* etag echoes
  are still honored for restarted serving processes.
- Program-run markdown and its static run reference (run instructions,
  smart clips) get independent etags, so a program edit no longer resends
  ~4KB of static instructions.
- skip_memory:true lets an agent that just wrote its memory files skip
  the immediate resend of content it authored.
- refresh:true resends everything; smith resets serve state natively on
  compact/prune, since the model no longer holds served content.
- Spec 0095 updated with the serving contract.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant