Bundled loops & the agent OS¶
A cartridge is a self-contained, signed harness — an agent-OS image — that any host boots by reading the cartridge's harness requirements, negotiating tools, activating the ROM, and running the loop the cartridge itself declares.
Most agent formats ship a prompt and hope the surrounding scaffolding matches. An .acx cartridge ships the scaffolding too: the loop shape, the context policy, the skills, the tool contract, and the memory all travel as one artifact, sealed under one signature. This page explains why that bundle is best understood as a portable operating system for an agent, grounds the framing in Lilian Weng's harness-engineering work, and walks the boot sequence a host follows to run one.
It draws on SPEC §8 (harness requirements), §9 (loop + context policy), and §9.6 (harness-engineering alignment). For the two-zone split that makes the image signable see the cartridge model; for the tool contract in detail see harness requirements.
The harness is the product¶
Lilian Weng, Harness Engineering for Self-Improvement (2026-07-04)
A harness is "the system surrounding a base model that orchestrates execution and decides how the model thinks and plans, calls tools and acts, perceives and manages context, stores artifacts, and evaluates results."
"The layer between the raw model and the real-world context seems to be as important as the model's raw intelligence."
Read that list of responsibilities again — plan, call tools, manage context, store artifacts, evaluate results — and notice that it enumerates, almost field for field, what an .acx cartridge carries:
| Weng's harness responsibility | Where it lives in a cartridge | SPEC |
|---|---|---|
| decides how the model thinks and plans | loop.cycle, loop.maxTurns, loop.stopConditions |
§9.2 |
| calls tools and acts | the four required tool-role contracts (acx:execute, acx:dispatch, acx:memory.write, acx:search) |
§8.4 |
| perceives and manages context | context.retrieval, context.compaction, context.toolResultTruncation |
§9.3 |
| stores artifacts | the memory partition + context.memoryFiles |
§7, §9.3 |
| evaluates results | loop.verification, and (v1.1) verification.regression |
§9.2, §9.6 |
The cartridge's contribution is not to invent this layer — it is to make it a portable, signable object. Weng's own warrant for treating the harness as a thing worth engineering is that an evolved harness transfers across benchmarks and tasks; if it transfers, it deserves to be packaged, versioned, and shipped. That is exactly what .acx does: it freezes the harness into the ROM zone, content-addresses it, and signs it.
The one-sentence claim
An .acx cartridge is an agent-OS image: the loop, the context policy, the skills, the tool contract, and the memory are bundled into one signed file, and a host boots it rather than merely reading a prompt from it.
Bundled loops: one artifact, not five files¶
"Bundled loops" is the design stance that these five layers must travel together, under one integrity boundary, or the guarantee dissolves.
Consider the alternative. If the loop policy lived in a repo, the skills in a package registry, the tool
list in a host config, and the memory in a database, then "this agent behaves the way its author intended"
would be an assertion about four independently mutable things. You could not sign, share, or reproduce
it as one unit. The cartridge collapses that into a single SQLite file where every behavior-defining part
is a sqlar row in the ROM zone, listed in the content-addressed integrity manifest, and covered by one
DSSE/ed25519 signature.
- The loop —
rom/policy/loop-context-policy.json(schemaVersion: "acx.loop-context-policy/1"), the declarative shape of the agentic cycle (SPEC §9.1). - The context policy — the
contextobject inside that same document: retrieval strategy, compaction intent, tool-result truncation, memory-file references (§9.3). - The skills —
SKILL.mdbundles underrom/skills/<name>/in thesqlartable, extractable by stocksqlite3(§5). - The tools contract —
rom/manifest/harness-requirements.json(schemaVersion: "acx.harness.v1"), four required roles plus an optional inventory (§8). - The memory — the always-present JSON baseline plus its zone partition (§7), the durable state the harness reads and writes.
Every item above is a ROM-zone artifact. That means each is listed in the self-excluding checksum.sha256 manifest and covered by the cartridge's detached DSSE signature over the recomputed ROM manifest hash. Mutating any one of them — the loop, a skill body, a tool contract — changes the manifest hash and flips trust to tampered:
verify (objects.oid tamper): invalid / tampered - ROM content diverges from signed manifest (object hash mismatch).
verify (SKILL.md content tamper, oid stale): invalid / tampered - ROM content diverges from signed manifest (object hash mismatch).
(verbatim from PROOF 2 in the proofs transcript)
Weng's discipline about where durable state lives is the same instinct at the file level:
Weng, on state
"A harness should not carry the entire workflow and all logs in context; instead, it should keep durable state in files."
The cartridge takes that literally: the workflow (loop), the notes (memory files), and the learned records (memory) are files inside the image, not context the model has to hold. The difference is that in an .acx those files are split by provenance — signed ROM versus mutable SAVE — so the durable state is not just persisted, it is attributable.
Weng's three patterns, mapped to cartridge features¶
Weng's post distills recurring harness structure into a small set of patterns. Three of them map cleanly onto concrete .acx fields — which is unsurprising, since the loop policy's v1.1 revision (SPEC §9.6) was written from this post.
Pattern 1 — the workflow loop¶
Weng
The core loop is to "plan, execute, observe/test, improve, and execute again until the goal is achieved."
The cartridge encodes this as data, not code, in loop.cycle. The canonical v1 phases are ["gather_context", "act", "verify"]; v1.1 (acx.loop-context-policy/1.1) additively permits plan and reflect, giving Weng's full five-beat loop:
{
"loop": {
"maxTurns": 40,
"cycle": ["plan", "gather_context", "act", "verify", "reflect"],
"verification": {
"commands": ["npm run lint", "npm test -- --changed"],
"scope": "touched",
"passIntent": "lint+types+touched tests green",
"blockOnFailure": true
},
"stopConditions": [
{ "when": "completed", "action": "stop" },
{ "when": "blocked", "action": "handoff" },
{ "when": "max_turns", "action": "handoff" }
]
}
}
This is a contract, not a runtime
SPEC §9.1 requires hosts to evaluate the policy as data — no recompilation to change loop behavior. The reference implementation validates and signs this document; the loop-policy evaluator that acts on it is specified, host-side, and is not part of the zero-dependency reference impl. The cartridge declares the loop; the host runs it.
Weng's "observe/test" beat is the cartridge's verify phase, and her acceptance criterion for self-improvement is the same one the provable-level protocol enforces cryptographically:
Weng, on acceptance
"Candidates are accepted only if they have no regression on both held-in and held-out data."
v1.1 adds loop.verification.regression {heldInSuite, heldOutSuite, acceptIf} to encode exactly that rule. A level (SPEC §10) is that same held-out-regression acceptance made into a signed, revocable credential — a strong agent earns it only after an independent re-run clears the σ-gate:
strong agent (competence 33): ISSUED ✅ | mu=33.03 sigma=1.232 games=90 passRate=60% R=29.34 => acxLevel=29 tier=principal
(PROOF 3; the reference solver that stands in for the graded agent run is deterministic and pluggable — a production verifier plugs in a real sandboxed agent.)
Pattern 2 — file-system as memory¶
Weng
"A harness should not carry the entire workflow and all logs in context; instead, it should keep durable state in files."
This is the memory partition and context.memoryFiles. Durable state lives in the .acx file, not the context window. Two features make it more than a flat file:
- Provenance split — every record carries a mandatory
portableboolean;portable: truerecords are signed ROM,portable: falserecords carry a privacy-preservingcodebaseFingerprintand stay in SAVE (SPEC §7.1). Field-learned records are quarantined by default:
- Portable baseline over vectors —
memory-records.jsonis the always-present source of truth; vectors are tagged with theembeddingEngineid and re-indexed on import, never trusted (§7.6). The reference impl uses a plain table here;vec0vectors are specified but host-side.
The context policy also declares how the harness spends its window without dictating a vendor algorithm: context.compaction is expressed as {preserve[], discard[], targetTokenBudget} intent over a fixed ContextCategory vocabulary, and targetTokenBudget is a target, not a trigger (§9.3). Anything vendor-specific — the summarization algorithm, KV-cache signals, context-editing strategy ids — is confined to an ignorable hints{} object, which brings us to Weng's forward-looking split:
Weng, on what endures
"Many harness improvements will be internalized into core model behavior, but the interface with external context and tools should remain."
That prediction is the §9.5 design: the durable interface (retrieval strategy, compaction intent, the outcome contract) is normative and declarative; the volatile model-specific mechanics live in hints{}, which a conformant host may ignore entirely and still run the loop.
Pattern 3 — explicit sub-agents¶
Weng
"Make parallelism explicit and inspectable."
The cartridge declares sub-agents as data in loop.subAgents, reusing the Agent SDK {description, prompt, tools} triple as {id, description, promptRef, tools[], concurrency, ...} (§9.2). Two safety rules come straight from the pattern:
- Sub-agents that write or make design decisions default to
concurrency: "single_threaded"; only read-only fan-out (search, review) may setparallel. - v1.1 adds
subAgents[].mode{sync | backend}for a monitorable long-running-job lifecycle — the "inspectable" half of Weng's rule.
Dispatching a sub-agent is itself a required tool role, acx:dispatch (scope dispatch), so a host that cannot spawn sub-agents fails the handshake rather than silently degrading (§8.4). Inspectability is backed by observability {tracer, decisionLog, pillars}, which ties runs to the repo audit log.
The boot sequence¶
Because the cartridge declares its own harness requirements, a host can treat it like a bootable image: read the requirements, negotiate a compliant environment, activate the signed ROM, run the declared loop, and let field learning write to SAVE. The handshake and the loop evaluator are specified normatively (§8.5); their runtime is host-side — the reference impl validates the manifests and the signature, not the live negotiation.
sequenceDiagram
autonumber
participant H as Host
participant C as .acx cartridge (ROM)
participant S as SAVE zone
H->>C: read rom/manifest/harness-requirements.json
Note over H,C: 4 required roles: acx:execute, acx:dispatch,<br/>acx:memory.write, acx:search
H->>C: signature-verify recomputed ROM manifest hash
Note over H: trusted / local / portable / legacy / tampered
H->>H: MCP initialize (protocol revision >= floor)
H->>C: negotiate — bind one concrete tool per role,<br/>grant capabilityScopes, emit compliance descriptor
alt any required role unbound or scope denied
H-->>C: verdict "refuse" (-32602 "Unsupported harness")
Note over H,S: ROM NOT activated · SAVE NOT mutated
else all required roles satisfied
H->>C: activate ROM — load loop-context-policy.json,<br/>skills, memory baseline
loop until stopCondition
H->>C: run declared cycle<br/>(plan → gather_context → act → verify → reflect)
end
H->>S: write field-learned records + rule-overlay.json
H-->>H: emit OperatorCommandReport
end
Two properties of this sequence are worth naming:
Refuse before activate — and never mutate SAVE on refusal
Per SPEC §8.5, if any of the four required roles is unbound or a required scope is denied, the host sets verdict: "refuse", emits the compliance descriptor and a JSON-RPC -32602 "Unsupported harness" error, and must not activate the ROM or mutate the SAVE zone. A cartridge also carries a preflight self-check that aborts if the persisted descriptor shows any required binding with satisfied: false. Boot is fail-closed.
Roles, not tool names
Authored ROM content invokes tools by role (acx:execute), never by a host-specific name (§8.2). The host maps one concrete tool onto each role at handshake time. This is what lets the same signed cartridge boot on different hosts — the reference tools agentibus_add_memory / agentibus_search_memory are just one possible binding for acx:memory.write / acx:search.
The host's own resource-limits.yaml always wins over the cartridge's budget defaults (§9.5): enforcement order is host policy > cartridge default, so a downloaded cartridge can never raise a consuming org's token or concurrency ceilings.
Why this is an operating system, precisely¶
The OS analogy is load-bearing, not decorative. An operating-system image (1) presents a stable syscall interface to programs, (2) is immutable and signed as shipped, and (3) writes runtime state to a separate mutable partition. A cartridge does all three:
- The syscall interface is the four
acx:tool roles plus the loop/context contract — the stable surface authored ROM content depends on, negotiated at boot. - The signed image is the ROM zone: content-addressed, DSSE-signed, and re-exportable to the identical manifest hash even after use.
rom hash before strip: sha256:f479be021b8ea2e55cc6e3e33b95df9d151196548dfc854dedbe578be7120642
rom hash after strip: sha256:f479be021b8ea2e55cc6e3e33b95df9d151196548dfc854dedbe578be7120642
hash-equality proof: EQUAL (ROM intact; SAVE removed)
- The mutable partition is the SAVE zone that the loop writes field-learned memory and
save/policy/rule-overlay.jsonto, quarantined from the signed core.
And like an OS image, it distributes as one immutable blob — the .acx is a single layer in an OCI image manifest (artifactType: application/vnd.acx.cartridge.v1), verifiable with stock cosign/oras (SPEC §11; the OCI push runtime is specified, host-side).
The whole bundle, in one inspect
== meta ==
acx.cartridge_id = io.github.agentibus/scenario-research-designer@025edd67-...
acx.rom_manifest_hash = sha256:f479be021b8ea2e55cc6e3e33b95df9d151196548dfc854dedbe578be7120642
== ROM objects ==
total: 21 (memory:1, cartridge:9, sqlar:11)
== skills (acx_skill) ==
- expertise-designer: Specialized designer expertise on research, ux, benchmarking...
== capabilities ==
- build-dag[pkg:generic/snowflake+pkg:pypi/apache-airflow+pkg:pypi/dbt-core] verified=false
== memory (by zone) ==
rom: 1
io.github.agentibus is an illustrative publisher handle.)
See also¶
- The cartridge model (ROM / SAVE) — the two-zone split that makes the image signable.
- Harness requirements — the four tool-role contracts and the negotiation handshake in full (SPEC §8).
- Skills — the
SKILL.mdbundles the loop draws on (SPEC §5). - Memory partition — the file-system-as-memory layer (SPEC §7).
- Provable level — held-out regression acceptance turned into a signed credential (SPEC §10).
- Distribution — shipping the agent-OS image over OCI (SPEC §11).
- Proofs — the verbatim transcript every code block on this page is quoted from.