Run-aware token governance for multi-agent systems.
Cap spend and steer behavior across a whole agent workflow — not per request — with a shared ledger and in-path enforcement.
TokenOps is a control plane + SDK for agent stacks. Entry agents register a run; every LLM and tool crossing shares one run_id and one ledger. Policies can halt, mutate, or inject before the next call executes — so a research → summarize → review pipeline stays inside a single budget even across processes.
Why · Architecture · Install · Quick start · Onboarding · Demos · Comparison · Make targets · Roadmap
- Govern the run, not the request. One
run_idspans every model, tool, and A2A hop in a workflow. - Shared ledger across processes. Spend, inflight, and halt live in SQLite so multi-agent stacks cannot each burn the full cap locally.
- In-path enforcement.
wrap_completeruns detect → decide → apply before the next LLM call; Chronicle@boundary+ a crossing hook ingest tool spend. - Steer or stop. Actuators:
HALT·MUTATE·INJECT· reject/queue — not just post-hoc analytics. - Batteries included. Control plane (
:7700), Admin + Dashboard UI, ten seeded policies, and runnable A2A benches (two-agent, triad, LangChain brief).
TokenOps is two layers that share one artifact, the run: a control plane that registers runs and stores budgets/policies, and an in-process SDK that enforces at every boundary crossing.
flowchart LR
subgraph PLANE["Control plane (:7700)"]
R["POST /v1/runs"] --> DB[("SQLite TOKENOPS_DB<br/>registrations · budgets · policies · ledger")]
UI["Admin + Dashboard"] --> DB
end
subgraph AGENTS["Agent processes (SDK)"]
E["Entry agent<br/>tokenops_run"] -->|"register_run"| R
E -->|"X-TokenOps-Run-Id"| D["Downstream agents<br/>tokenops_run"]
E & D -->|"wrap_complete"| G["Governor<br/>pre_call → detect → decide → apply"]
E & D -->|"@boundary + crossing hook"| G
G --> L["Shared ledger<br/>(same run_id)"]
end
L --> DB
DB -->|"governance_config_for"| G
| Piece | Owns | Does not own |
|---|---|---|
Control plane (python -m tokenops.server) |
POST /v1/runs, shared SQLite, Admin/Dashboard |
Agent loops, LLM calls, tools |
| SDK (in agents) | tokenops_run, wrap_complete, ledger/policies, Chronicle crossing hook |
Ad-hoc run IDs; mounting /v1/runs when TOKENOPS_URL is set |
Chronicle records decision boundaries; TokenOps attaches as the cost/governance observer on live crossings. See Chronicle for record-and-replay.
pip install agent-tokenops
# With example / bench extras (LangChain, ddgs):
pip install "agent-tokenops[examples]"
# From source (development):
pip install -e ".[dev,examples]"Prerequisites: Python 3.10+; agent-tokenops; either a running control plane
(TOKENOPS_URL + shared TOKENOPS_DB) or TOKENOPS_EMBEDDED=1 for single-process /
tests. LLM API keys only for real model calls. FastAPI only if you use
instrument_app.
PyPI name is agent-tokenops; import is still tokenops (same pattern as Chronicle).
See RELEASING.md for releases.
make install
cp .env.example .env # optional API keys for demos / your agents
make db-reset # optional: clean SQLite + seed governance from default.yaml
make run # control plane :7700 + Admin/Dashboard :8501Wire governance into an agent: instrument_app once, then tokenops_run per request.
The UI sends task only; intent / mode come from agent config on instrument_app.
from tokenops import ControlPlaneClient, instrument_app, tokenops_run
from tokenops.control import wrap_complete, with_governance_errors
from tokenops.providers import complete
client = ControlPlaneClient.from_env() # TOKENOPS_URL or embedded Store
async def handler(payload: dict, headers: Mapping[str, str]) -> dict:
with tokenops_run(client=client) as bound:
governed = wrap_complete(
bound.governor, bound.controls, bound.attr,
provider=provider, model=model,
dispatch=complete, service="planner",
)
run_agent(..., complete_fn=governed)
app = create_a2a_app(..., handler=with_governance_errors(handler))
instrument_app(app, service="planner", intent="triad_plan",
provider=provider, model=model)Non-FastAPI: TokenOps does not yet ship middleware for other frameworks. Use
bind_request_context(RequestContext(headers=..., payload=..., service=...)) then
with tokenops_run():, or pass those kwargs explicitly to tokenops_run.
Point agents at the plane and share one DB:
export TOKENOPS_URL=http://localhost:7700
export TOKENOPS_DB=tokenops.db # plane + all agents
make control-plane # :7700
make ui # Admin + Dashboard :8501New here? Onboarding guide (prereqs, bare-min integrate, FAQ, current limits).
Full integration checklist: .cursor/skills/integrate-tokenops/SKILL.md · triad deep dive: docs/guides/field-guide-add-tokenops.md.
Each bench is a multi-agent stack with a shared run ledger. Start the plane, agents, and Admin UI with one make target.
| Demo | Agents | Run |
|---|---|---|
| Two-agent | Research → Summarize | make demo |
| Triad | Planner → Researcher → Writer | make demo-triad |
| Brief | Scout → Analyst → Editor (LangChain) | make demo-brief |
| Bench UI | Chat + Simulator only | make bench-ui |
make demo # plane + research/summarize + Admin UI
make demo-triad # plane + planner/researcher/writer
make demo-brief # plane + scout/analyst/editorDocker:
docker compose up --build
# optional UI: docker compose --profile ui up --build
# two-agent stack:
docker compose -f docker-compose.examples.yml up --buildSee examples/README.md and docs/control-plane-deploy.md.
TokenOps is not a gateway or a tracing dashboard. It governs the run — a full agent workflow — and sits alongside the tools you already use for routing and observability.
| TokenOps | LiteLLM / Portkey / AI Gateway | Langfuse | |
|---|---|---|---|
| Primary focus | Run (stateful) | Request | Trace (observe) |
| Multi-agent workflow as one unit | Yes | No | Manual stitch |
| Budget enforcement in-path | Yes (run-aware) | Yes (key/team) | No (analytics) |
| Steer next call (mutate / inject) | Yes | Routing / fallbacks | No |
| Shared ledger across agent processes | Yes | N/A | N/A |
What this does not do: replace your LLM gateway, replace Chronicle-style record-and-replay, or host a SaaS control plane for you. Fail-closed integrity (refuse on missing registration) is optional and upcoming.
Longer table with logos: docs/product/comparison.md.
Command reference
| Target | Role |
|---|---|
make install |
Editable install with dev + examples extras |
make dist / check-dist |
Build sdist+wheel / twine check |
make control-plane |
Standalone plane (python -m tokenops.server) on :7700 |
make ui |
Admin + Dashboard on :8501 |
make run |
Plane + Admin/Dashboard |
make demo / demo-triad / demo-brief |
Runnable A2A stacks |
make bench-ui |
Chat + Simulator |
make db-reset |
Clear SQLite + reseed from TOKENOPS_CONFIG |
make stop |
Kill listeners on :7700 / :8501 |
| Variable | Purpose |
|---|---|
TOKENOPS_URL |
Remote plane base URL (e.g. http://localhost:7700) → HTTP register_run |
TOKENOPS_EMBEDDED |
Set to 1 to force in-process Store (tests / single-process) |
TOKENOPS_DB |
SQLite path shared by plane + agents |
TOKENOPS_CONFIG |
YAML for governance seed (core: src/tokenops/config/default.yaml) |
Production / multi-process: set TOKENOPS_URL; agents must not mount /v1/runs. Tests: TOKENOPS_EMBEDDED=1 (or omit URL).
Only src/tokenops/ is the installable package. Demos and benches stay under examples/.
src/tokenops/ # installable package
├── server/ # control plane (:7700, POST /v1/runs)
├── control/ # SDK: ledger, policies, wrap_complete, crossing hook
├── providers/ # OpenAI / Anthropic complete dispatch
├── config/ # default.yaml governance seed
└── ui/ # Admin + Dashboard (Streamlit)
examples/ # A2A benches (two-agent, triad, brief) + Chat/Simulator
benchmarking/ # MetaGPT / browser-use live harness
docs/ # architecture, policies, guides, product
tests/ # unit + e2e
TokenOps is early (0.x). Near-term:
- User/tag segment-scoped budgets (machinery exists; seed is run-only today).
- Optional fail-closed mode on missing registration or exceeded budget.
- Remote observe / decide (fatter plane) for multi-host stacks.
- Documentation site.
Status of each control-plane job: docs/control-plane-status.md. Ideas welcome via GitHub issues.
- Onboarding — prereqs, bare-min integrate, FAQ, current limits
- Field guide — triad deep dive + screenshots
- Control plane status
- Architecture
- Run attribution
- Control plane deploy
- Examples
- Product: comparison · shared ledger
Issues and PRs are welcome. See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md.
make install
make lint
make testThanks to everyone who has contributed.
If TokenOps saves you a runaway agent bill, please ⭐ star the repo so more people can find it.
Built by Susheem Koul and Tisha Chawla