TokenOps control plane and SDK for run-aware agent token governance
Project description
TokenOps
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
Why TokenOps
- 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).
Architecture
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.
Install
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.
Quick start
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 :8501
Wire 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 :8501
New 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.
Demos
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/editor
Docker:
docker compose up --build
# optional UI: docker compose --profile ui up --build
# two-agent stack:
docker compose -f docker-compose.examples.yml up --build
See examples/README.md and docs/control-plane-deploy.md.
How TokenOps compares
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.
Make targets
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 |
Environment variables
| 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).
Project structure
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
Roadmap
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.
Documentation
- 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
Contributing
Issues and PRs are welcome. See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md.
make install
make lint
make test
Contributors
Thanks 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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_tokenops-0.1.3.tar.gz.
File metadata
- Download URL: agent_tokenops-0.1.3.tar.gz
- Upload date:
- Size: 112.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d07258a5ac6c1540992bb8e9a00717804fe648dada80df352abcba401ee0f1a5
|
|
| MD5 |
db947bbc3381ea7308c9b1bfcddd9dbb
|
|
| BLAKE2b-256 |
20ef1cd60b88b54f248a822699f727a1c15ec6220b4c5172f16616e4d1d79f2c
|
Provenance
The following attestation bundles were made for agent_tokenops-0.1.3.tar.gz:
Publisher:
release.yml on theagentplane/tokenops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_tokenops-0.1.3.tar.gz -
Subject digest:
d07258a5ac6c1540992bb8e9a00717804fe648dada80df352abcba401ee0f1a5 - Sigstore transparency entry: 2235410591
- Sigstore integration time:
-
Permalink:
theagentplane/tokenops@39455dfd5de4bb47b8d9b1bca5c5ee504709ad79 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/theagentplane
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@39455dfd5de4bb47b8d9b1bca5c5ee504709ad79 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file agent_tokenops-0.1.3-py3-none-any.whl.
File metadata
- Download URL: agent_tokenops-0.1.3-py3-none-any.whl
- Upload date:
- Size: 106.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b61bf7ef9e9fa9d74e0883430bca3185694972d5a3a7e7bbe2947641f2a28b4a
|
|
| MD5 |
ab86f0b9d420633a1bdb927b4f3fbe10
|
|
| BLAKE2b-256 |
d984208cd5f1168bbaceea8c48fa1eaa0618895358d7ef79a58b96ca85db5317
|
Provenance
The following attestation bundles were made for agent_tokenops-0.1.3-py3-none-any.whl:
Publisher:
release.yml on theagentplane/tokenops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_tokenops-0.1.3-py3-none-any.whl -
Subject digest:
b61bf7ef9e9fa9d74e0883430bca3185694972d5a3a7e7bbe2947641f2a28b4a - Sigstore transparency entry: 2235410713
- Sigstore integration time:
-
Permalink:
theagentplane/tokenops@39455dfd5de4bb47b8d9b1bca5c5ee504709ad79 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/theagentplane
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@39455dfd5de4bb47b8d9b1bca5c5ee504709ad79 -
Trigger Event:
workflow_dispatch
-
Statement type: