Files
buzz/docs/agent-context-compiler.md
Salman Mohammed 33909a352f Add deterministic agent context compiler
Signed-off-by: Salman Mohammed <smohammed@squareup.com>
2026-08-21 13:54:45 -04:00

5.0 KiB

Agent context compiler

Buzz compiles every event-driven ACP turn into one deterministic dynamic envelope. Standing platform, persona, team, core-memory, and channel-canvas content remains in session/new's system role when an adapter supports it; the manifest still records those inputs and their session-start freshness.

Standing context uses the same paired-boundary convention so long sections are easy to delimit:

<workspace>...</workspace>
<base>...</base>
<system>...</system>
<team-instructions>...</team-instructions>
<core-memory>...</core-memory>
<huddle-instructions>...</huddle-instructions>
<channel-canvas>...</channel-canvas>
<buzz-turn>
  <ambient-context>
    Scope: thread
    Channel: engineering
    <recent-thread-delta included="2" total="2" truncated="false">
      Morgan: The deploy is failing.
    </recent-thread-delta>
  </ambient-context>
  <event type="mention" author="Morgan"
      actor="pubkey" event_id="event-id">
    Content: Fix the deployment failure.
  </event>
  <delivery ... />
</buzz-turn>

The grammar deliberately uses tags only at ambient context, history, current event, and delivery boundaries. Human-readable fields carry ordinary channel and message content without duplicating every fact in nested attributes. Natural-language content and attribute values are still escaped deterministically. The format is XML-like but is not an XML protocol: consumers should recognize the semantic boundaries and must not require a general XML parser. Raw Nostr tags are deliberately absent. Event IDs, actors, normalized thread routing, and mentions remain in the envelope; a signed event can be fetched when needed with buzz messages raw --event ….

Recent ambient messages stay deliberately terse (Author: content). Their signed event IDs, timestamps, and actor keys still feed the content-addressed layer version, so different relay heads produce different manifests without repeating forensic metadata in the model's active context.

Every model-visible ambient fragment participates in the manifest. Retrieval status and interrupted-turn evidence therefore change the manifest even when the current signed instruction is unchanged. Channel metadata and channel canvas are separate order-4 entries: metadata is resolver-cached, while canvas content is frozen when the ACP session starts.

The pure compiler does no I/O and reads no clock, environment variable, or session identifier. Present layers are ordered canonically, empty layers are omitted, content versions are SHA-256 hashes unless a signed source event ID is available, and the manifest hash covers the canonical serialized layer array. The manifest is emitted to local observer diagnostics and included in encrypted NIP-AM metrics when the harness reports usage.

An ACP steer accepted as injected is appended to the active turn ledger by the prompt read loop before it acknowledges delivery. The terminal NIP-AM metric consequently hashes both the original prompt and every accepted update; failed or indeterminate steers are not added. Local diagnostics emit prompt_context_steer with the resulting manifest. An adapter response of startedNewTurn is reported as a distinct diagnostic and is deliberately not folded into the already-settled turn's manifest.

Queue dispatch is the authority boundary. Contiguous events are coalesced only when both their signing actor and destination match. A thread's root event ID is its destination; each top-level event is its own destination. Different actors, thread roots, and unrelated top-level instructions therefore produce separate turns.

Significant implementation diversions

  • There is one Buzz-owned compiler in buzz-acp, rather than a duplicate compiler inside buzz-agent. Native buzz-agent is an ACP adapter and consumes the same compiled envelope as Goose, Codex, and Claude adapters. Keeping two renderers would weaken the determinism requirement.
  • Layer 5 (thread_checkpoint) is omitted because Buzz does not yet have the checkpoint artifact proposed in Proposal 4. The manifest intentionally omits absent layers instead of fabricating a checkpoint.
  • The proposal's attention caps remain experiments, as requested, rather than hard-coded budgets. Existing bounded thread retrieval supplies the current truncation signal; the compiler records it without introducing a second, unvalidated truncation policy.
  • Provider-specific four-slot cache partitioning is not forced through ACP, which cannot express cache breakpoints. Native buzz-agent retains its existing stable system/tool prefix and rolling-tail breakpoints; deterministic serialization improves automatic prefix reuse for every adapter. A distinct channel-snapshot breakpoint requires an ACP capability or native-only prompt interpretation and is deferred rather than creating adapter drift.
  • Rollout is direct rather than feature-flagged. The legacy bracketed parser is retained in Desktop diagnostics for stored observer history, while all new event-driven turns use the semantic envelope.