The control plane for safe, scalable agent tool and API execution.
OpenToolplane sits between an agent and the HTTP tools or APIs it calls. The agent decides what to do. OpenToolplane decides how that work runs in production: with retries, rate limits, idempotency, caching, async execution, quotas, and auditability.
It is built for the moment when agent workflows stop being demos and start behaving like real distributed systems. Instead of re-implementing execution policy inside every agent, you centralize it in one runtime.
Use OpenToolplane when your agents need to:
- fan out across many APIs without overwhelming downstream systems
- make mutating calls safely with idempotency and audit logs
- queue long-running work and deliver results via callbacks
- enforce tenant-specific tool access and quotas
- survive restarts without losing jobs, tool definitions, or runtime state
OpenToolplane is less useful if your system is a single-process demo with a small number of trusted internal tools and no multi-tenant or operational requirements.
The fastest way to understand OpenToolplane is to watch three behaviors:
- the same read is served from cache instead of hitting the provider twice
- the same write is replayed safely instead of creating a duplicate side effect
- a slow tool runs in the background and completes through a signed webhook callback
Start the stack:
docker compose up --buildIn another terminal, run the guided demo:
python examples/clarity_demo.pyThat script walks through the system and prints the evidence from the control plane and the mock downstream services.
For the demo narrative, see examples/CLARITY_DEMO.md.
- durable async jobs stored in the service database
- lease-based workers and webhook delivery recovery after process restart
- retries with exponential backoff and jitter
- circuit breaking
- idempotency-key replay for mutating calls
- short-lived caching for readonly calls
- shared rate limiting and concurrency control backed by the service database
- persisted tool registry, so registered tools survive restart
- API-key auth with admin and invoke scopes
- tenant-aware tool visibility and quotas
- signed webhook callbacks for async jobs
- audit log for registration, invocation, jobs, and webhook delivery
/readyzand Prometheus/metrics- OpenTelemetry-compatible spans through
opentelemetry-api
- OpenAPI import with
x-agent-policy
Agent
-> OpenToolplane
-> tool registry
-> policy enforcement
-> rate limits / concurrency / retries
-> cache / idempotency / background jobs
-> webhook delivery / audit / metrics / traces
-> downstream HTTP tools and APIs
OpenToolplane uses a single durable database as its coordination layer.
That means:
- jobs, callbacks, idempotency state, cache entries, and tool definitions survive restart
- multiple app instances pointed at the same database can share execution budgets and safely claim work
- no external queue is required for an initial production deployment
This release currently supports sqlite:/// database URLs. That makes it suitable for local use, pilots, and simple first deployments. The next scale-up step is the same coordination model backed by Postgres and Redis.
python -m venv .venv
source .venv/bin/activate
pip install -e .
export OPENTOOLPLANE_POLICY_FILE=examples/policies.yaml
export OPENTOOLPLANE_AUTH_REQUIRED=true
export OPENTOOLPLANE_API_KEYS='[
{"key_id":"admin","value":"otp-admin-local","scopes":["admin"]},
{"key_id":"tenant-a","value":"otp-tenant-a-local","scopes":["invoke"],"tenant_id":"tenant-a"}
]'
export OPENTOOLPLANE_TENANT_QUOTAS='{
"tenant-a": {"requests_per_minute": 300, "max_concurrent_requests": 10, "max_background_jobs": 25}
}'
uvicorn app.main:app --reload --port 8080Run the example downstream services in separate terminals:
uvicorn examples.mock_provider:app --port 8090
uvicorn examples.mock_webhook_receiver:app --port 8091docker compose up --buildThis starts:
- OpenToolplane on
http://localhost:8080 - mock downstream provider on
http://localhost:8090 - mock webhook receiver on
http://localhost:8091
Demo API keys in docker-compose.yml:
- admin:
otp-admin-local - tenant-a invoke:
otp-tenant-a-local
curl http://localhost:8080/healthz
curl http://localhost:8080/readyzcurl http://localhost:8080/v1/tools \
-H 'x-api-key: otp-tenant-a-local'curl -X POST http://localhost:8080/v1/tools \
-H 'content-type: application/json' \
-H 'x-api-key: otp-admin-local' \
-d '{
"name": "orders.create",
"description": "Create an order",
"request": {
"method": "POST",
"url_template": "http://localhost:8090/orders"
},
"policy": {
"idempotent": true,
"retry": {"max_attempts": 3}
},
"allowed_tenants": ["tenant-a"]
}'curl -X POST http://localhost:8080/v1/tools/orders.create:invoke \
-H 'content-type: application/json' \
-H 'x-api-key: otp-tenant-a-local' \
-d '{
"body": {"sku": "sku-123", "quantity": 1},
"idempotency_key": "order-123"
}'curl -X POST http://localhost:8080/v1/tools/reports.daily:invoke \
-H 'content-type: application/json' \
-H 'x-api-key: otp-tenant-a-local' \
-d '{
"async_mode": true,
"callback": {
"url": "http://localhost:8091/callback",
"secret": "demo-secret",
"headers": {"x-receiver": "demo"}
}
}'Then inspect the job and callback delivery:
curl http://localhost:8080/v1/jobs/<job_id> \
-H 'x-api-key: otp-tenant-a-local'
curl http://localhost:8080/v1/jobs/<job_id>/deliveries \
-H 'x-api-key: otp-tenant-a-local'Operations can include x-agent-policy and x-allowed-tenants.
curl -X POST http://localhost:8080/v1/tools/import/openapi \
-H 'content-type: application/json' \
-H 'x-api-key: otp-admin-local' \
-d @examples/openapi-import-payload.jsoncurl 'http://localhost:8080/v1/audit?limit=20' \
-H 'x-api-key: otp-admin-local'curl http://localhost:8080/metricstools:
- name: catalog.get_item
description: Fetch a catalog item
request:
method: GET
url_template: http://localhost:8090/catalog/items/{item_id}
policy:
readonly: true
timeout_ms: 3000
concurrency:
max_in_flight: 8
rate_limit:
enabled: true
capacity: 16
refill_per_second: 8
caching:
enabled: true
ttl_seconds: 60
allowed_tenants:
- tenant-aapp/ FastAPI service, runtime, storage, auth, execution engine
examples/ guided demo, mock provider, webhook receiver, sample policy and OpenAPI payload
issues/ backlog as issue-style markdown files
tests/ API and runtime tests
pytest -q