Skip to content

Epic: remote-only control plane — hard HTTP dependency for the ledger #118

Description

@susheem-k

Umbrella for making TokenOps hard-dependent on the HTTP control plane for the
ledger: remove the local-file / embedded path from the agent, move run state to the
plane, keep per-turn latency sane. Absorbs #55 and #60; coordinates with
agentplane-control-plane (see its epic).

Full working plan + wire contract: scratch/remote-only-control-plane-plan.md and
scratch/phase-0-contract.md in the repo (contract moves to
control-plane/docs/api-contract.md when Phase 1 starts).

Decisions (locked)

  1. POST /v1/ledger/precheck — one consolidated read per governed call.
  2. POST /v1/ledger/events:batch — one batched write; single-op ledger routes become wrappers.
  3. Idempotency key required on every write event; plane dedupes.
  4. Run state (steps/window/velocity) moves to the plane (run_state table); Tier-1 LocalRunState stays as a per-process cache.
  5. Policies carry data_scope ∈ {local, global}; local reads Tier-1 only, global reads the plane via precheck.
  6. No client-side event buffer yet — apply_events(list) is the only write path so a buffer can wrap it later.
  7. No accuracy-loss bounding — budgets stay a soft cap.
  8. trajectory_hint disabled (done); no trajectory/* routes.
  9. RunState → LocalRunState (rename).
  10. Budget fan-out = one spent_add event with all targets; plane applies in one txn.
  11. Inflight-counter safety (call-id set) is out of scope → Inflight ledger is a bare per-segment counter — not safe under async/batched/retried admit·complete #116.
  12. run_registrations merged into runs; identity columns write-once; create_run removed from the agent path → Merge run_registrations into runs; make identity columns write-once; stop agents calling create_run #117.
  13. One runs row per run_id — no per-agent participation rows.
  14. span_id removed from TokenOps entirely; cross-hop link is X-TokenOps-Run-Id only.
  15. No TOKENOPS_EMBEDDED — unit tests use an in-memory FakeLedgerBackend, kept honest by a contract suite parametrized against the real plane over httpx.ASGITransport.
  16. UI lives in the plane — delete src/tokenops/ui/ and the streamlit dependency.

Update (0.3.0, 2026-09-12): the hard HTTP dependency landed — no more local ledger
fallback, from_env() requires a URL, Ledger(backend=...) is wired end to end. Epic
stays open: data_scope-based detector grouping, span_id removal, server/ui
teardown, and Phase 3/4 are still outstanding. See checklist below.

Phases

Phase 0 — contract & decisions ✅

  • Wire contract (scratch/phase-0-contract.md)
  • Plane-unreachable behavior settled (3 modes + circuit breaker)
  • trajectory_hint disabled in code

Phase 1 — agentplane-control-plane → 0.2.0 ✅ merged

control-plane#12 merged (closes control-plane#10): precheck, events:batch,
run_state, data_scope, run-scoped halt, PRAGMA user_version migrations,
registered_at, PATCH narrowing, start/stop/status CLI, Dockerfile. Additive —
0.1-era clients still work. Destructive fold deferred → control-plane#11 (0.3.0, not
required for this epic).

Phase 2 — tokenops SDK

Phase 3 — tests & CI

Phase 4 — follow-ups

Sub-issues

#113 (run/trace/span terminology) · #114 (governance-config TTL) · #115 (LocalRunState leak) · #116 (inflight counter) · #117 (run_registrations/runs merge)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions