agent-tokenops 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_tokenops-0.2.1/PKG-INFO +401 -0
- agent_tokenops-0.2.1/README.md +354 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/pyproject.toml +4 -2
- agent_tokenops-0.2.1/src/agent_tokenops.egg-info/PKG-INFO +401 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/agent_tokenops.egg-info/SOURCES.txt +5 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/agent_tokenops.egg-info/requires.txt +2 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/__init__.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/engine.py +36 -3
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/__init__.py +4 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/concurrency_cap.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/context_compaction.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/cost_guard.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/output_runaway.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/pre_call_worst_case.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/progress_guard.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/step_cap.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/tool_fix.py +1 -1
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/tool_output_cap.py +1 -1
- agent_tokenops-0.2.1/src/tokenops/demo.py +113 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/theme.py +34 -26
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/views/dashboard.py +18 -2
- agent_tokenops-0.2.1/tests/test_a2a_health.py +140 -0
- agent_tokenops-0.2.1/tests/test_demo.py +89 -0
- agent_tokenops-0.2.1/tests/test_policy_coordination.py +125 -0
- agent_tokenops-0.2.1/tests/test_reason_encoding.py +78 -0
- agent_tokenops-0.2.0/PKG-INFO +0 -324
- agent_tokenops-0.2.0/README.md +0 -278
- agent_tokenops-0.2.0/src/agent_tokenops.egg-info/PKG-INFO +0 -324
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/LICENSE.txt +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/setup.cfg +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/agent_tokenops.egg-info/dependency_links.txt +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/agent_tokenops.egg-info/top_level.txt +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/adapters/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/adapters/langchain.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/config/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/config/default.yaml +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/config/loader.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/attribution.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/boundary.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/client.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/config.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/context.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/core.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/crossing.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/governance_cache.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/http.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/http_store.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/instrument.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/integration.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/ledger.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/models.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/_util.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/cost_budget.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/policies/trajectory_hint.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/pricing.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/propagate.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/request_context.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/run.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/store.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/compress.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/enqueue.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/gates.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/hint.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/scope.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/serialize.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/control/trajectory/worker.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/env.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/providers/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/providers/anthropic.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/providers/factory.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/providers/openai.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/providers/types.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/server/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/server/__main__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/server/app.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/app.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/run_detail.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/store_client.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/views/__init__.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/src/tokenops/ui/views/admin.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_actuators.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_apply.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_attribution.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_attribution_ledger_policies_e2e.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_boundary.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_chronicle_boundary.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_concurrency_cap.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_config.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_context_compaction.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_control_plane_app.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_control_plane_client.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_cost_budget.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_cost_guard.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_cross_process_budget_gating.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_crossing_hook.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_governance_config_cache.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_governance_per_agent.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_integration.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_ledger.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_llm_boundary_precall.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_output_runaway.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_policies_wrap_integration.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_pre_call_worst_case.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_preview_mode.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_pricing.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_progress_guard.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_propagate.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_server_enforcement.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_step_cap.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_store.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_thread_safety.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_tokenops_run.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_tool_fix.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_tool_output_cap.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_trajectory_hint.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_trajectory_hint_e2e.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_wrap_adapters.py +0 -0
- {agent_tokenops-0.2.0 → agent_tokenops-0.2.1}/tests/test_wrap_complete_chronicle.py +0 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-tokenops
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: TokenOps control plane and SDK for run-aware agent token governance
|
|
5
|
+
Author: Susheem Koul, Tisha Chawla
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/theagentplane/tokenops
|
|
8
|
+
Project-URL: Repository, https://github.com/theagentplane/tokenops
|
|
9
|
+
Project-URL: Issues, https://github.com/theagentplane/tokenops/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/theagentplane/tokenops/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: llm,agents,governance,token-budget,multi-agent,control-plane,cost-control
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Systems Administration
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE.txt
|
|
23
|
+
Requires-Dist: agent-chronicle>=0.3.0
|
|
24
|
+
Requires-Dist: openai>=1.0
|
|
25
|
+
Requires-Dist: anthropic>=0.40
|
|
26
|
+
Requires-Dist: pyyaml>=6.0
|
|
27
|
+
Requires-Dist: python-dotenv>=1.0
|
|
28
|
+
Requires-Dist: streamlit<2,>=1.38
|
|
29
|
+
Requires-Dist: httpx>=0.27
|
|
30
|
+
Requires-Dist: fastapi>=0.115
|
|
31
|
+
Requires-Dist: uvicorn>=0.32
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=6.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.8; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=1.13; extra == "dev"
|
|
39
|
+
Requires-Dist: pre-commit>=4.0; extra == "dev"
|
|
40
|
+
Requires-Dist: types-PyYAML>=6.0; extra == "dev"
|
|
41
|
+
Provides-Extra: examples
|
|
42
|
+
Requires-Dist: ddgs>=9.0; extra == "examples"
|
|
43
|
+
Requires-Dist: langchain-core>=0.3; extra == "examples"
|
|
44
|
+
Requires-Dist: langchain-openai>=0.2; extra == "examples"
|
|
45
|
+
Requires-Dist: langchain-anthropic>=0.2; extra == "examples"
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
|
|
48
|
+
<div align="center">
|
|
49
|
+
|
|
50
|
+
# TokenOps
|
|
51
|
+
|
|
52
|
+
**Cuts wasted agent spend by up to `65%`, governing what the run has already spent before every call.**<br>
|
|
53
|
+
<sub>Toward token governance as a first-class discipline, not an afterthought.</sub>
|
|
54
|
+
|
|
55
|
+
[](https://pypi.org/project/agent-tokenops/)
|
|
56
|
+
[](https://pepy.tech/project/agent-tokenops)
|
|
57
|
+
[](LICENSE.txt)
|
|
58
|
+
[](https://github.com/theagentplane/tokenops/stargazers)
|
|
59
|
+
[](https://www.linkedin.com/company/the-agent-plane/)
|
|
60
|
+
[](https://github.com/theagentplane/tokenops/discussions)
|
|
61
|
+
|
|
62
|
+
[](https://www.linkedin.com/posts/microsoft-developers_who-spent-all-the-tokens-tokenops-gives-activity-7499191980715982848-224b)
|
|
63
|
+
[](https://commandline.microsoft.com/tokenops-real-time-run-scoped-cost-control-ai-agents/)
|
|
64
|
+
[](https://www.youtube.com/watch?v=GJX19pNhmSw)
|
|
65
|
+
|
|
66
|
+
<sub>Built by <b><a href="https://www.linkedin.com/in/susheemkoul/">Susheem Koul</a></b> and <b><a href="https://www.linkedin.com/in/tisha-chawla/">Tisha Chawla</a></b></sub>
|
|
67
|
+
|
|
68
|
+
<table><tr><td>
|
|
69
|
+
|
|
70
|
+
<img src="https://raw.githubusercontent.com/theagentplane/tokenops/main/docs/assets/devto-cover.png" alt="TokenOps: one budget for one whole agent run, enforced before every model call" width="720" />
|
|
71
|
+
|
|
72
|
+
</td></tr></table>
|
|
73
|
+
|
|
74
|
+
<sub><i>See it stop a run mid-budget in the <a href="#-quickstart">Quickstart</a> below.</i></sub>
|
|
75
|
+
|
|
76
|
+
<br>
|
|
77
|
+
|
|
78
|
+
[Core features](#-core-features) · [Quickstart](#-quickstart) · [Quickdeploy](#-quickdeploy) · [How it compares](#-how-tokenops-compares) · [Policies](docs/policies/) · [Support](#-support) · [Contributing](#-open-to-contribution)
|
|
79
|
+
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
> ### 🙌 Open to contribution
|
|
83
|
+
>
|
|
84
|
+
> Token spend deserves the same first-class attention as compute or latency, and
|
|
85
|
+
> we are growing the community working on that. Policies, actuators, and the
|
|
86
|
+
> shared ledger are all open to extension. See
|
|
87
|
+
> **[CONTRIBUTING.md](CONTRIBUTING.md)** to get started.
|
|
88
|
+
|
|
89
|
+
## ✨ Core features
|
|
90
|
+
|
|
91
|
+
An AI agent's workflow can run up cost fast: dozens of small, individually
|
|
92
|
+
cheap steps that quietly add up to a surprisingly large bill. TokenOps sets
|
|
93
|
+
a single budget for the whole workflow and enforces it before every step,
|
|
94
|
+
so spending never gets away from you.
|
|
95
|
+
|
|
96
|
+
<img src="docs/assets/core-features.svg" alt="TokenOps core features: enforced pre-call, run-scoped budget, shared across processes, steers not just stops, tool calls count too, ten policies included" width="850" />
|
|
97
|
+
|
|
98
|
+
Ten policies ship configured in [`docs/policies/`](docs/policies/), and you can
|
|
99
|
+
add your own.
|
|
100
|
+
|
|
101
|
+
## 🚀 Quickstart
|
|
102
|
+
|
|
103
|
+
Requires Python 3.10+.
|
|
104
|
+
|
|
105
|
+
### 1. Put it in your agent
|
|
106
|
+
|
|
107
|
+
> [!TIP]
|
|
108
|
+
> **Recommended.** Your coding assistant reads
|
|
109
|
+
> [`SKILL.md`](.claude/skills/integrate-tokenops/SKILL.md), wires the one
|
|
110
|
+
> enforcement point into your agent, and tells you what to check.
|
|
111
|
+
|
|
112
|
+
In **Claude Code**, from a clone:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
/integrate-tokenops
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Anywhere else (Cursor, Copilot, ...), paste this:
|
|
119
|
+
|
|
120
|
+
> Integrate TokenOps into this agent, following
|
|
121
|
+
> https://github.com/theagentplane/tokenops/blob/main/.claude/skills/integrate-tokenops/SKILL.md
|
|
122
|
+
|
|
123
|
+
<details>
|
|
124
|
+
<summary><b>Manual</b>, about ten lines</summary>
|
|
125
|
+
|
|
126
|
+
Wrap your model call once, then hand the wrapped version to your agent.
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from tokenops import ControlPlaneClient, tokenops_run
|
|
130
|
+
from tokenops.control import Halt, wrap_complete
|
|
131
|
+
from tokenops.providers import complete
|
|
132
|
+
|
|
133
|
+
client = ControlPlaneClient.from_env()
|
|
134
|
+
|
|
135
|
+
with tokenops_run(client=client, service="my-agent", intent="research",
|
|
136
|
+
provider="openai", model="gpt-4o") as bound:
|
|
137
|
+
governed = wrap_complete(
|
|
138
|
+
bound.governor, bound.controls, bound.attr,
|
|
139
|
+
provider="openai", model="gpt-4o",
|
|
140
|
+
dispatch=complete, service="my-agent",
|
|
141
|
+
)
|
|
142
|
+
try:
|
|
143
|
+
agent.run(..., complete_fn=governed) # <-- pass `governed`, not `complete`
|
|
144
|
+
except Halt as stopped:
|
|
145
|
+
print(f"run stopped: {stopped}")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Pass `governed` to your agent instead of `complete`; nothing else changes.
|
|
149
|
+
`wrap_complete` checks the budget before each call and raises `Halt` when the
|
|
150
|
+
run is out, even from another process.
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
### 2. When you need more
|
|
155
|
+
|
|
156
|
+
| You want to | Go to |
|
|
157
|
+
|---|---|
|
|
158
|
+
| Change the budget | [Set the budget](.claude/skills/integrate-tokenops/SKILL.md#set-the-budget) |
|
|
159
|
+
| One budget across several agent processes | [Shared plane](.claude/skills/integrate-tokenops/SKILL.md#tier-2--several-processes-one-budget) |
|
|
160
|
+
| FastAPI or A2A services | [Instrumented app](.claude/skills/integrate-tokenops/SKILL.md#tier-3--fastapi--a2a) |
|
|
161
|
+
| Something other than stopping | [The ten policies](docs/policies/) |
|
|
162
|
+
| Cost per agent in a dashboard | [Quickdeploy](#-quickdeploy) |
|
|
163
|
+
| A worked end-to-end example | [Field guide](docs/guides/field-guide-add-tokenops.md) |
|
|
164
|
+
| Everything else | [Onboarding guide](docs/guides/onboarding.md) |
|
|
165
|
+
|
|
166
|
+
### 3. See it in action
|
|
167
|
+
|
|
168
|
+
<table><tr><td>
|
|
169
|
+
|
|
170
|
+
<a href="https://github.com/theagentplane/tokenops/raw/main/examples/demo-assets/videos/02_governance_on_budget_cap.webm">
|
|
171
|
+
<img src="https://raw.githubusercontent.com/theagentplane/tokenops/main/examples/demo-assets/videos/02_governance_on_budget_cap.gif" alt="TokenOps demo: the same task run twice - ungoverned, it completes over budget; governed, TokenOps halts it within the cap - then the Dashboard shows spend and governance per agent" width="760" />
|
|
172
|
+
</a>
|
|
173
|
+
|
|
174
|
+
</td></tr></table>
|
|
175
|
+
|
|
176
|
+
<sub><i>Same task, run twice: ungoverned it completes over budget, governed it halts within the cap, then the Dashboard attributes cost per agent. <a href="https://github.com/theagentplane/tokenops/raw/main/examples/demo-assets/videos/02_governance_on_budget_cap.webm">Full video</a>.</i></sub>
|
|
177
|
+
|
|
178
|
+
## 🐳 Quickdeploy
|
|
179
|
+
|
|
180
|
+
> [!TIP]
|
|
181
|
+
> The control plane (`python -m tokenops.server`) shares one budget across
|
|
182
|
+
> processes and powers the dashboard. A single-process agent doesn't need it
|
|
183
|
+
> running at all.
|
|
184
|
+
|
|
185
|
+
One command, plane + dashboard:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
git clone https://github.com/theagentplane/tokenops && cd tokenops
|
|
189
|
+
docker compose --profile ui up --build
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Plane: `localhost:7700/health` · Dashboard: `localhost:8501`. Plane only:
|
|
193
|
+
`docker compose up --build`. Details: [`docs/control-plane-deploy.md`](docs/control-plane-deploy.md).
|
|
194
|
+
|
|
195
|
+
<details>
|
|
196
|
+
<summary><b>Without Docker</b> (make)</summary>
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
git clone https://github.com/theagentplane/tokenops && cd tokenops
|
|
200
|
+
make install
|
|
201
|
+
make run # control plane :7700 + Admin/Dashboard :8501
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Then open `localhost:8501` to see spend and governance per agent.
|
|
205
|
+
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
<details>
|
|
209
|
+
<summary><b>Multi-agent benches</b>: watch one budget span several agents</summary>
|
|
210
|
+
|
|
211
|
+
Each is a real multi-agent stack sharing one run ledger. One target starts the
|
|
212
|
+
plane, the agents, and the Admin UI.
|
|
213
|
+
|
|
214
|
+
| Bench | Agents | Run |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| Two-agent | Research to Summarize | `make demo` |
|
|
217
|
+
| Triad | Planner to Researcher to Writer | `make demo-triad` |
|
|
218
|
+
| Brief | Scout to Analyst to Editor (LangChain) | `make demo-brief` |
|
|
219
|
+
| Bench UI | Chat + Simulator only | `make bench-ui` |
|
|
220
|
+
|
|
221
|
+
`cp .env.example .env` first if you want them to call real models. See
|
|
222
|
+
[`examples/README.md`](examples/README.md) for the bench profiles.
|
|
223
|
+
|
|
224
|
+
</details>
|
|
225
|
+
|
|
226
|
+
<details>
|
|
227
|
+
<summary><b>Pointing several processes at one plane</b></summary>
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
export TOKENOPS_URL=http://localhost:7700
|
|
231
|
+
export TOKENOPS_DB=tokenops.db # plane and every agent read the same file
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
> `TOKENOPS_EMBEDDED=1` overrides `TOKENOPS_URL`. Leave it unset here, or each
|
|
235
|
+
> process silently falls back to its own local ledger and gets the full budget.
|
|
236
|
+
|
|
237
|
+
PyPI name is `agent-tokenops`; the import is `tokenops`. Extras:
|
|
238
|
+
`pip install "agent-tokenops[examples]"` for the LangChain benches,
|
|
239
|
+
`".[dev,examples]"` from source. Releases: [`RELEASING.md`](RELEASING.md).
|
|
240
|
+
|
|
241
|
+
</details>
|
|
242
|
+
|
|
243
|
+
## 🆚 How TokenOps compares
|
|
244
|
+
|
|
245
|
+
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.
|
|
246
|
+
|
|
247
|
+
| | TokenOps | LiteLLM / Portkey / AI Gateway | Langfuse |
|
|
248
|
+
|---|:---:|:---:|:---:|
|
|
249
|
+
| Primary focus | Run | Request | Trace |
|
|
250
|
+
| Multi-agent workflow as one unit | Yes | No | Partial |
|
|
251
|
+
| Budget enforcement in-path | Yes | Yes | No |
|
|
252
|
+
| Steer next call (mutate / inject) | Yes | Partial | No |
|
|
253
|
+
| Shared ledger across processes | Yes | — | — |
|
|
254
|
+
|
|
255
|
+
What this does **not** do: replace your LLM gateway, replace Chronicle-style record-and-replay, or host a SaaS control plane for you.
|
|
256
|
+
|
|
257
|
+
Longer table with logos: [`docs/product/comparison.md`](docs/product/comparison.md).
|
|
258
|
+
|
|
259
|
+
## Reference
|
|
260
|
+
|
|
261
|
+
Things you will want eventually, not now.
|
|
262
|
+
|
|
263
|
+
<details>
|
|
264
|
+
<summary><b>Architecture: how the plane and the SDK split the work</b></summary>
|
|
265
|
+
|
|
266
|
+
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.
|
|
267
|
+
|
|
268
|
+
```mermaid
|
|
269
|
+
flowchart LR
|
|
270
|
+
subgraph PLANE["Control plane (:7700)"]
|
|
271
|
+
R["POST /v1/runs"] --> DB[("SQLite TOKENOPS_DB<br/>registrations · budgets · policies · ledger")]
|
|
272
|
+
UI["Admin + Dashboard"] --> DB
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
subgraph AGENTS["Agent processes (SDK)"]
|
|
276
|
+
E["Entry agent<br/>tokenops_run"] -->|"register_run"| R
|
|
277
|
+
E -->|"X-TokenOps-Run-Id"| D["Downstream agents<br/>tokenops_run"]
|
|
278
|
+
E & D -->|"wrap_complete"| G["Governor<br/>pre_call → detect → decide → apply"]
|
|
279
|
+
E & D -->|"@boundary + crossing hook"| G
|
|
280
|
+
G --> L["Shared ledger<br/>(same run_id)"]
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
L --> DB
|
|
284
|
+
DB -->|"governance_config_for"| G
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
| Piece | Owns | Does not own |
|
|
288
|
+
|---|---|---|
|
|
289
|
+
| **Control plane** (`python -m tokenops.server`) | `POST /v1/runs`, shared SQLite, Admin/Dashboard | Agent loops, LLM calls, tools |
|
|
290
|
+
| **SDK (in agents)** | `tokenops_run`, `wrap_complete`, ledger/policies, Chronicle crossing hook | Ad-hoc run IDs; mounting `/v1/runs` when `TOKENOPS_URL` is set |
|
|
291
|
+
|
|
292
|
+
Chronicle records decision boundaries; TokenOps attaches as the cost/governance observer on live crossings. See [Chronicle](https://github.com/theagentplane/chronicle) for record-and-replay.
|
|
293
|
+
|
|
294
|
+
</details>
|
|
295
|
+
|
|
296
|
+
<details>
|
|
297
|
+
<summary><b>Environment variables</b></summary>
|
|
298
|
+
|
|
299
|
+
| Variable | Purpose |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `TOKENOPS_URL` | Remote plane base URL (e.g. `http://localhost:7700`) → HTTP `register_run` |
|
|
302
|
+
| `TOKENOPS_EMBEDDED` | Set to `1` to force in-process `Store` (tests / single-process) |
|
|
303
|
+
| `TOKENOPS_DB` | SQLite path shared by plane + agents |
|
|
304
|
+
| `TOKENOPS_CONFIG` | YAML for governance seed (core: `src/tokenops/config/default.yaml`) |
|
|
305
|
+
|
|
306
|
+
`TOKENOPS_URL` also accepts the aliases `CONTROL_PLANE_URL` and
|
|
307
|
+
`TOKENOPS_CONTROL_PLANE_URL`.
|
|
308
|
+
|
|
309
|
+
Production / multi-process: set `TOKENOPS_URL`; agents must **not** mount `/v1/runs`. Tests: `TOKENOPS_EMBEDDED=1` (or omit URL).
|
|
310
|
+
|
|
311
|
+
> **Precedence.** `ControlPlaneClient.from_env` takes the HTTP path only when a
|
|
312
|
+
> URL is set **and** `TOKENOPS_EMBEDDED` is not `1`. Setting both falls back to a
|
|
313
|
+
> local SQLite file with no warning, and every process then gets its own full
|
|
314
|
+
> budget. Check with
|
|
315
|
+
> `print("embedded" if client.embedded else client.url)`.
|
|
316
|
+
|
|
317
|
+
</details>
|
|
318
|
+
|
|
319
|
+
<details>
|
|
320
|
+
<summary><b>Make targets</b></summary>
|
|
321
|
+
|
|
322
|
+
| Target | Role |
|
|
323
|
+
|--------|------|
|
|
324
|
+
| `make install` | Editable install with dev + examples extras |
|
|
325
|
+
| `make dist` / `check-dist` | Build sdist+wheel / `twine check` |
|
|
326
|
+
| `make control-plane` | Standalone plane (`python -m tokenops.server`) on `:7700` |
|
|
327
|
+
| `make ui` | Admin + Dashboard on `:8501` |
|
|
328
|
+
| `make run` | Plane + Admin/Dashboard |
|
|
329
|
+
| `make demo-quick` | `python -m tokenops.demo`: no API keys, no server |
|
|
330
|
+
| `make demo` / `demo-triad` / `demo-brief` | Runnable A2A stacks |
|
|
331
|
+
| `make bench-ui` | Chat + Simulator |
|
|
332
|
+
| `make db-reset` | Clear SQLite + reseed from `TOKENOPS_CONFIG` |
|
|
333
|
+
| `make stop` | Kill listeners on `:7700` / `:8501` |
|
|
334
|
+
| `make sync-skills` | Regenerate the editor copies of the integration skill |
|
|
335
|
+
|
|
336
|
+
</details>
|
|
337
|
+
|
|
338
|
+
<details>
|
|
339
|
+
<summary><b>Project structure</b></summary>
|
|
340
|
+
|
|
341
|
+
Only `src/tokenops/` is the installable package. Demos and benches stay under `examples/`.
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
src/tokenops/ # installable package
|
|
345
|
+
├── server/ # control plane (:7700, POST /v1/runs)
|
|
346
|
+
├── control/ # SDK: ledger, policies, wrap_complete, crossing hook
|
|
347
|
+
├── providers/ # OpenAI / Anthropic complete dispatch
|
|
348
|
+
├── config/ # default.yaml governance seed
|
|
349
|
+
└── ui/ # Admin + Dashboard (Streamlit)
|
|
350
|
+
examples/ # A2A benches (two-agent, triad, brief) + Chat/Simulator
|
|
351
|
+
benchmarking/ # MetaGPT / browser-use live harness
|
|
352
|
+
docs/ # architecture, policies, guides, product
|
|
353
|
+
tests/ # unit + e2e
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
</details>
|
|
357
|
+
|
|
358
|
+
<details>
|
|
359
|
+
<summary><b>More documentation</b></summary>
|
|
360
|
+
|
|
361
|
+
- [Onboarding](docs/guides/onboarding.md): prereqs, minimum integration, FAQ, current limits
|
|
362
|
+
- [Field guide](docs/guides/field-guide-add-tokenops.md): a triad walked through, with screenshots
|
|
363
|
+
- [Policies](docs/policies/): one page per policy
|
|
364
|
+
- [Run attribution](docs/run-attribution.md) - [control plane deploy](docs/control-plane-deploy.md) - [status](docs/control-plane-status.md)
|
|
365
|
+
- [Examples](examples/README.md) - [comparison](docs/product/comparison.md) - [shared ledger](docs/product/shared-ledger.md)
|
|
366
|
+
|
|
367
|
+
</details>
|
|
368
|
+
|
|
369
|
+
## 📰 Talks & press
|
|
370
|
+
|
|
371
|
+
- **Featured by Microsoft Developer**: “Who spent all the tokens?” on
|
|
372
|
+
[LinkedIn](https://www.linkedin.com/posts/microsoft-developers_who-spent-all-the-tokens-tokenops-gives-activity-7499191980715982848-224b) and [X](https://x.com/msdev/status/2093425027500978292).
|
|
373
|
+
- **[Who spent all the tokens? Real-time, run-scoped cost control for AI agents](https://commandline.microsoft.com/tokenops-real-time-run-scoped-cost-control-ai-agents/)**: *Command Line*, a Microsoft publication.
|
|
374
|
+
- **[FinOps for AI Agents: Who Spent All the Tokens?](https://www.youtube.com/watch?v=GJX19pNhmSw)**: talk at the **AI Engineer World's Fair**, San Francisco.
|
|
375
|
+
|
|
376
|
+
## 🛟 Support
|
|
377
|
+
|
|
378
|
+
| Need | Where |
|
|
379
|
+
|---|---|
|
|
380
|
+
| Bug | [Open an issue](https://github.com/theagentplane/tokenops/issues) |
|
|
381
|
+
| Security issue | [SECURITY.md](SECURITY.md) |
|
|
382
|
+
| Real-time help | [Slack](https://join.slack.com/t/theagentplane/shared_invite/zt-47lqx2xtc-0idr1cuLNJ_JDTgqxDiUsg) |
|
|
383
|
+
| Longer-form discussion | [GitHub Discussions](https://github.com/theagentplane/tokenops/discussions) |
|
|
384
|
+
| Talk it through | [Office hours](https://calendly.com/theagentplane/theagentplane) |
|
|
385
|
+
| Talks & writing | [theagentplane.github.io/media](https://theagentplane.github.io/media.html) |
|
|
386
|
+
|
|
387
|
+
## Contributors
|
|
388
|
+
|
|
389
|
+
Thanks to everyone who has contributed.
|
|
390
|
+
|
|
391
|
+
[](https://github.com/theagentplane/tokenops/graphs/contributors)
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
Saved you tokens? [⭐ Star the repo](https://github.com/theagentplane/tokenops).
|
|
396
|
+
|
|
397
|
+
<div align="center">
|
|
398
|
+
|
|
399
|
+
[Back to top](#tokenops)
|
|
400
|
+
|
|
401
|
+
</div>
|