OpenWOP openwop.dev
RFC details authors, dates, what it affects, review history
FieldValue
RFC0111
TitleContext Economy — Transcript Token Budget & Declared Summarization
StatusAccepted
Author(s)David Tufts (@davidscotttufts)
Created2026-06-26
Updated2026-09-26 — Active (Parked) → Accepted. Evidence tier: tier-2 — MyndHyve workflow-runtime, the steward-affiliated sibling host; single witness. The tripwire fired: a host running real orchestrator-loop model turns advertises contextBudget and produced a non-vacuous witness. Deployed revision workflow-runtime-00788-peh, build commit:9e5216d4d2ce93e34aaec195a47645b370943119 (its live /readiness answers that commit); live discovery advertises multiAgent.executionModel.contextBudget {transcriptTokenBudget: 520, tokenCounter: "chars", summarization: {supported: true, keepLastTurns: 2}} and lists conformance-context-budget-live — re-fetched at the moment of this flip. Evidence: evidence/rfc-witnesses/0111-myndhyve-major1-2.42.1.json (file sha256 3a1eef59054c…, witnessSha256 fd41a368bef6…), signed myndhyve-bundle-2026-09b (= the live discovery signingKeys[0]), steward-verified with the PUBLISHED suite 2.42.1 (--verify --host-key → VERIFIED). context-budget-transcript-bound executed-pass (27 assertions) and context-summarization-replay executed-pass (15 assertions), at scenario and it level, with no partial-witness detail — so the #1606 pressure check saw a real eviction or summary, the chars recount of entries[].rendered equalled tokenCount, and a replay fork fed the model the recorded summary byte-for-byte. The bundle is NOT certified, and this RFC does not claim a certification: 1415 pass / 168 fail / 190 blocked / 303 inapplicable / 27 skipped, the failing and blocked rows overwhelmingly v1 host-sample seams this host does not mount at major 1. Replay-adjacent rows among them, named so none is hidden: replay-fanout-suppression, aiEnvelope.correlationReplay, the compensation-behavior/recovery replay legs, dispatch-per-item-input replay, replay-divergence-at-refusal, replay-llm-cache-key, replay-retention-expiry — none is one of this RFC's scenarios. Steward decision, recorded as such: this RFC predates the RFC 0167 certification program (check-accepted-predicate.mjs does not bind it), and its bar is GOVERNANCE §"Acceptance evidence tiers": a witnessed, non-vacuous conformance pass on a deployed host, which a signed per-requirement bundle is; a certified bundle is not required. The witness is at major 1 because at major 2 both scenarios gate on the seams-profile claim (conformance.seamsProfile), which MyndHyve production does not make — at major 2 they record inapplicable, which witnesses nothing. Getting here found and fixed six real host defects (myndhyve #498 AI-call dedup key, #499 thinking-token cap, #500 loop turns replaying turn 1's cached output + model 429 retry, #502 server-side Gemini via Vertex, #504 replay fork re-emits recorded supervisor/dispatch outcomes, #505 replay fork carries the replayed turns' transcript windows) and two suite defects (#1606 the witness could not fail; #1625 a hard-coded 30 s test timeout no live run could meet). Not provisional: no comment-window waiver is recorded for this RFC (filed at Active 2026-06-26 under the bootstrap rules of the time), so it has no RFC 0156 §B register row. · 2026-09-26 — amended in place (additive): the fork refusal names its code. The summary-unavailable refusal said only "mirroring replay_memory_snapshot_unavailable" and named no code, so the first implementing host had to emit a vendor code for a condition this RFC owns. It is now replay_context_summary_unavailable (409, not retriable), registered in spec/v2/errors.json since 2.42 and listed in v1 rest-endpoints.md §"Common error codes". It binds only hosts advertising contextBudget.summarization (none in production at amendment time), so no existing pass changes. No conformance leg asserts the code: a black-box suite cannot make a host's summary artifact unavailable at fromSeq, so the code is advertise-and-attest, like the off-seam ceiling of the transcript seam. · Parked 2026-08-13 — tripwire: a host running real orchestrator-loop model turns advertises contextBudget and produces a non-vacuous witness. No steward host does; the mock supervisor is forbidden from advertising it by this RFC's own §Scope, and openwop-app confirmed on 2026-08-13 that it runs no real orchestrator turns. All five acceptance boxes are ticked and the RFC still does not graduate — criterion 5's tick covers deferring reference-host implementation for Active, and the same sentence names this tripwire as the Accepted gate. Counting the boxes says ready; reading them says not yet. 2026-06-26
Affectsspec/v1/multi-agent-execution.md, spec/v1/host-sample-test-seams.md, schemas/capabilities.schema.json, schemas/run-event-payloads.schema.json, conformance
Compatibilityadditive per COMPATIBILITY.md
Supersedes—
Superseded by—

Summary

A v1-conformant host MAY feed an unbounded transcript to each orchestrator turn: multi-agent-execution.md §"Stateful agent-loop lifecycle" defines transcriptWindow as an event-count bound and states "Absent ⇒ unbounded on the wire." This RFC adds an opt-in contextBudget object to the multi-agent execution-model capability that lets a host advertise (a) a per-turn token budget for the orchestrator transcript and (b) a declared summarization contract for turns evicted beyond that budget — making the per-iteration context contract observable and conformance-testable. It does not change any existing default: a host that advertises neither field behaves exactly as today.

Motivation

The protocol is byte-lean on the wire (content-free events, reference-by-id payloads, updates delta streams as the default) but says nothing normative about the prompt a host assembles and sends to the model each iteration. A third-party token-efficiency red-team (2026-06-15) identified this as the dominant cost: a conformant host re-sending the full transcript each turn grows per-turn cost O(turns) and cumulative run cost O(turns²). Two facts make this a spec concern rather than a pure implementation choice:

  1. transcriptWindow already exists (RFC 0061, version >= 5) but bounds by event count, which does not bound tokens — a single large tool result blows the budget regardless of count.
  2. The spec is silent on what a host does with evicted turns. Per COMPATIBILITY.md §4, a new normative requirement on previously-undefined behavior is additive — so the spec is the right place to define a budgeted, summarization-aware context contract that hosts can advertise and clients can rely on.

This RFC makes the contract declarable without forcing it on anyone: the "kill the unbounded default" framing from the red-team is deliberately not adopted, because flipping absent ⇒ unbounded to absent ⇒ bounded is a behavior change requiring the safety-fix process. Opt-in advertisement is the additive-safe path.

Proposal

Capability surface

Add an optional contextBudget object under multiAgent.executionModel (the same object that carries transcriptWindow). It is version >= 5 (RFC 0061 stateful loop) gated.

   "executionModel": {
     "type": "object",
     "properties": {
       "transcriptWindow": { "type": "integer", "minimum": 1 },
+      "contextBudget": {
+        "type": "object",
+        "additionalProperties": false,
+        "properties": {
+          "transcriptTokenBudget": {
+            "type": "integer", "minimum": 1,
+            "description": "RFC 0111. Max tokens of transcript the host feeds any single orchestrator turn. Advertise-and-honor; complements (does not replace) transcriptWindow. Absent ⇒ no token bound."
+          },
+          "tokenCounter": {
+            "type": "string",
+            "enum": ["o200k_base", "cl100k_base", "chars", "host-defined"],
+            "description": "RFC 0111. The unit transcriptTokenBudget is denominated in, so the bound is interpretable across hosts. REQUIRED when transcriptTokenBudget is present. Same enum as RFC 0113 memory.injectionBudget.tokenCounter — transcript + memory budgets denominate consistently."
+          },
+          "summarization": {
+            "type": "object",
+            "additionalProperties": false,
+            "properties": {
+              "supported": { "type": "boolean" },
+              "strategy": { "type": "string", "enum": ["sliding-window", "recursive", "map-reduce"] },
+              "keepLastTurns": { "type": "integer", "minimum": 0,
+                "description": "Turns kept verbatim at the head of the window; older turns MAY be replaced by a summary." }
+            },
+            "required": ["supported"]
+          }
+        }
+      }
     }
   }

Normative requirements

  • Scope. contextBudget governs the RFC 0061 per-iteration orchestrator-loop transcript — multi-agent-execution.md §"Per-iteration state inputs" input 3, the SAME transcript transcriptWindow bounds — NOT a general chat-conversation history (RFC 0005) or any other prompt. A host whose multi-agent orchestrator loop does not run real model turns (e.g. a mock supervisor with no live inference) MUST NOT advertise contextBudget, exactly as it MUST NOT dishonestly advertise transcriptWindow. Budget-only advertisement (transcriptTokenBudget + tokenCounter without summarization.supported) is valid for a host that HAS a real orchestrator loop but does not summarize.
  • A host advertising contextBudget.transcriptTokenBudget MUST NOT feed more than that many tokens of transcript to any single orchestrator turn, measured in the unit named by contextBudget.tokenCounter.
  • A host advertising transcriptTokenBudget MUST also advertise tokenCounter; the budget is otherwise uninterpretable.
  • transcriptTokenBudget and transcriptWindow MAY both be advertised; when both are present the host MUST honor whichever bound is tighter for a given turn.
  • A host advertising contextBudget.summarization.supported: true MUST keep the most recent keepLastTurns turns verbatim and MAY replace older in-window turns with a host-produced summary. The active (most recent) turn MUST NOT be summarized.
  • Replay determinism (normative). Per multi-agent-execution.md §"Per-iteration state inputs", the transcript is a deterministic, replay-reproducible iteration input — today a pure projection of the event-log tail. A host-produced summary is nondeterministic host output that breaks that purity, so it is governed exactly like a nondeterministic LLM envelope under RFC 0041 (version >= 5 implies the version >= 4 replay-determinism contract). Therefore:

- Each substitution MUST be recorded as a context.summarized event (payload below) whose summaryRef points at the persisted summary. - On a POST /v1/runs/{runId}:fork mode: replay, when a summarization point falls at sequence ≥ fromSeq, the host MUST reuse the recorded summary (resolved via summaryRef) and MUST NOT re-summarize. A host that re-summarizes and produces a different model-facing transcript is non-conformant — the direct analogue of RFC 0041 §"Envelope-refusal recovery in replay". - summaryRef is an artifactId (a run-produced artifact read via GET /v1/runs/{runId}/artifacts/{artifactId}), keeping the event content-free. By direct analogy to the MAE-3 memory carry-forward (multi-agent-execution.md §"Replay carry-forward"), the summary artifact MUST be persisted and readable as-of the iteration's event-log index; a host that cannot serve it at the requested fromSeq MUST refuse the fork with replay_context_summary_unavailable (mirroring replay_memory_snapshot_unavailable; code named by the 2026-09-26 amendment — see Updated). - Summarization that is not recorded this way breaks replay and MUST NOT be advertised under this capability.

Event-payload addition

schemas/run-event-payloads.schema.json gains context.summarized:

{
  "type": "context.summarized",
  "payload": {
    "iteration": 12,
    "replacedTurns": ["evt_0a1", "evt_0a2"],
    "summaryRef": "art_sum_7c",
    "tokenCounter": "o200k_base",
    "tokensBefore": 4120,
    "tokensAfter": 280
  }
}

summaryRef is a reference-by-id to the summary artifact (the summary text is not inlined on the wire — content-free event discipline). replacedTurns lists the event ids the summary stands in for, so a replay engine can reconstruct the exact transcript.

Conformance seam

The assembled transcript is host-internal and never crosses the wire, so conformance cannot observe it from discovery alone. This RFC adds one seam to host-sample-test-seams.md:

GET /v1/host/sample/agent/transcript-window?runId=…&iteration=N
→ { tokenCounter, tokenCount, eventIds: [...], summarizedRanges: [...] }

The seam returns the host's own accounting of what it fed the model that iteration. Conformance: drive enough turns that an unbounded transcript would exceed the budget, then assert (a) tokenCount ≤ transcriptTokenBudget; (b) the harness independently re-computes the token sum and confirms the host's reported tokenCount is internally consistent and ≤ budget — corrected 2026-09-26 (COMPATIBILITY.md, an assertion no implementation could satisfy: events are content-free, so the event log gives the harness nothing to count). The seam now also returns entries[] { eventId, rendered }, the exact text fed per item; for tokenCounter: "chars" it is REQUIRED and the harness sums the rendered code points, which MUST equal tokenCount; every entry is a real event of the run and the verbatim entries are eventIds in order. For o200k_base, cl100k_base and host-defined the recount is advertise-and-attest (the suite ships no tokenizer). No host MUST moved; (c) eventIds are the recent tail (no older event included while a newer eligible one is dropped — eligible meaning sharing (type, nodeId) with an event fed that turn, defined 2026-09-26 because the RFC had left it undefined); and (d) every summarizedRanges entry has a matching context.summarized event. A full witness also needs pressure — at least one turn where the budget evicted or summarized an older eligible event; a run whose transcript never reaches the advertised budget records partial-witness, not a pass (suite 2.41.0).

Honest non-vacuity limit (documented, not a gap to close): the model-facing prompt is genuinely host-internal, so conformance verifies the host's declared transcript accounting is internally consistent and within budget — it cannot black-box-prove the host doesn't additionally feed off-seam content to the model. This is the inherent ceiling of governing host-internal assembly via a test seam; the capability is advertise-and-attest, and the seam proves the accounting is consistent + bounded, not that the prompt is nothing more. A host that lies in the seam fails the cross-check in (b)/(c); a host that lies past the seam is outside what any wire/seam witness can see.

Examples

Positive — host advertises a 4 000-token budget with sliding-window summarization keeping the last 3 turns verbatim:

{ "multiAgent": { "executionModel": { "version": 5,
  "contextBudget": { "transcriptTokenBudget": 4000, "tokenCounter": "o200k_base",
    "summarization": { "supported": true, "strategy": "sliding-window", "keepLastTurns": 3 } } } } }

Negative — transcriptTokenBudget without tokenCounter (uninterpretable budget) → fails schema (tokenCounter required when budget present, enforced by an if/then clause) and fails conformance.

Compatibility

Additive. Backward-compat clauses:

  • contextBudget is a new optional object; a host that omits it behaves exactly as today (transcriptWindow semantics, including absent ⇒ unbounded, are untouched).
  • context.summarized is a new event type per COMPATIBILITY.md §2.1; consumers that do not recognize it ignore it. Server-emitted event schemas are open (RFC 0094), so adding it does not break schema-validating clients.
  • replay_context_summary_unavailable (amended 2026-09-26) is a new registered error code: it names the refusal this RFC already required, binds only hosts advertising contextBudget.summarization, and registering a code is additive (COMPATIBILITY.md §2.1; precedent: the 2.36 registry rows added by RFCs 0199/0201/0210).
  • No existing field changes type, optionality, or meaning. No default flips. The "bound the transcript by default" option was explicitly rejected as a §4 behavior change (see Alternatives).

Conformance

  • Existing: multi-agent-* scenarios cover the execution loop and transcriptWindow count semantics; none assert a token bound.
  • New: context-budget-transcript-bound.test.ts, gated on capabilityFamily(d,'multiAgent')?.executionModel?.contextBudget?.transcriptTokenBudget being present (soft-skip on absence). Drives a multi-turn run, reads the host-sample transcript seam each iteration, asserts tokenCount ≤ budget and that keepLastTurns recent turns appear verbatim. A second scenario context-summarization-replay.test.ts (gated on summarization.supported) replays the run and asserts the reconstructed transcript matches, exercising the context.summarized → summaryRef path.

Alternatives considered

  1. Flip the default (absent ⇒ bounded). The red-team's headline. Rejected: per COMPATIBILITY.md §4 this changes observed behavior on hosts that never advertised a window → safety-fix process, not additive. Not worth a v1.x break for an efficiency optimization hosts can already perform.
  2. Leave it host-internal (do nothing). Hosts can already token-budget their own prompt assembly with zero conformance impact (Tier-A in the red-team). Rejected as the whole answer because it leaves the contract unobservable: a client cannot tell whether a host bounds context, so cross-host portability of "this agent stays cheap on long runs" is impossible. The capability advertisement is the value-add.
  3. Reuse RFC 0084 budget-policy maxTokens. Rejected: maxTokens is a run-wide spend ceiling that fails or interrupts the run on exhaustion; it is not a per-turn context-shaping budget and has no summarization semantics.

Unresolved questions

  1. Should tokenCounter permit provider-native counters (e.g., a named Anthropic/OpenAI tokenizer) or stay at a small portable enum? The enum keeps conformance deterministic but may diverge from a host's real provider count.
  2. Is keepLastTurns the right knob, or should the verbatim floor be expressed in tokens (keepLastTokens) to compose with transcriptTokenBudget?
  3. Does context.summarized belong in the normative core event set, or behind the same version >= 5 gate as the rest of the stateful loop?
  4. Should the transcript seam be normative here or deferred to a host-sample-only test seam (as drafted)?

Implementation notes (non-normative)

  • Tier-A host patches that need no spec change and SHOULD ship independently of this RFC: provider context-caching (byte-identical, front-loaded system prompt), per-task tool sub-allowlisting, gzipped SSE bus, stripping optional event meta. This RFC governs only the declarable transcript contract; the rest is host craft.
  • Sequence after the schema lands: reference host (sqlite) implements the seam + a sliding-window summarizer first; it is the simplest strategy and exercises the context.summarized replay path.
  • Reconcile with openwop-app ADR 0148 A1 (host-internal token-budgeted transcript assembly + transcriptWindow advert): A1 is the Tier-A producer of exactly the budgeted transcript that contextBudget advertises and the seam witnesses — the host's A1 assembly path emits the context.summarized event + the seam reads its accounting. One model, not two.
  • tokenCounter shares the RFC 0113 enum (incl. chars), so a host budgets transcript (0111) and memory (0113) in one consistent unit.

Acceptance criteria

  • [x] Spec text merged (multi-agent-execution.md §contextBudget + host-sample-test-seams.md seam) — landed with the Active surface 2026-06-26 (CHANGELOG [Unreleased]).
  • [x] capabilities.schema.json + run-event-payloads.schema.json updated — contextBudget (capabilities) + context.summarized (run-event-payloads) both on main.
  • [x] context-budget-transcript-bound.test.ts + context-summarization-replay.test.ts in @openwop/openwop-conformance — both present; capability-gated + driver-based, so they exercise non-vacuously only against a host advertising contextBudget on a real orchestrator loop.
  • [x] CHANGELOG entry under the next minor — [Unreleased] "RFCs 0111 / 0114 / 0116 — token-economy surfaces (Active, 2026-06-26)".
  • [x] A reference host advertises contextBudget and passes both scenarios non-vacuously, or the RFC explicitly defers reference-host implementation — this RFC takes the deferral: no current steward reference host runs a real orchestrator-loop model turn to witness against (the mock supervisor MUST NOT advertise contextBudget per §"Scope"). Both conformance scenarios soft-skip on non-advertising hosts; the non-vacuous witness comes from a host that runs real orchestrator turns (the Active → Accepted graduation gate). Gate met 2026-09-26: a host advertising contextBudget on a real orchestrator loop passes both scenarios non-vacuously — MyndHyve (tier-2), see Updated.

References

  • spec/v1/multi-agent-execution.md §"Stateful agent-loop lifecycle" (transcriptWindow, line 238).
  • spec/v1/budget-policy.md (RFC 0084) — run-wide spend, contrasted in Alternatives.
  • COMPATIBILITY.md §4 (behavior-only changes) — the §4 table is why the default cannot flip.
  • RFC 0061 (stateful agent-loop lifecycle), RFC 0041 (replay determinism), RFC 0094 (schema closure).
  • Prior art: Anthropic prompt caching; LangGraph checkpoint/summarization; sliding-window context management.
  • Sibling RFCs in this set: 0112 (compact tools), 0113 (memory budget), 0114 (A2UI deltas), 0115 (transport economy), 0116 (prompt-prefix cache).

More proposals.

Edit this page on GitHub ↗