Metadata-Version: 2.4
Name: tbay
Version: 0.3.0
Summary: Execution safety for AI agent tool calls: idempotency, semantic caching, singleflight, policy, budgets, a kill switch, approval gating, and a reasoning-linked audit log, as a library, not a service.
Author: tbay contributors
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Requires-Dist: click>=8.1
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9; extra == "postgres"
Provides-Extra: redis
Requires-Dist: redis>=4.2; extra == "redis"
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.20; extra == "otel"
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: psycopg2-binary>=2.9; extra == "dev"
Requires-Dist: redis>=4.2; extra == "dev"
Requires-Dist: opentelemetry-sdk>=1.20; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Dynamic: license-file

# tbay

[![installs](https://static.pepy.tech/personalized-badge/tbay?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=yellow&left_text=Downloads)](https://pepy.tech/projects/tbay) ![GitHub stars](https://img.shields.io/github/stars/akhilkanduri/tbay)


Execution safety for AI agent tool calls: idempotency, TTL and semantic
caching, singleflight deduplication, risk-tiered policy, spend budgets, a
cross-process kill switch, human approval gating (optionally
cryptographically signed), crash recovery, lifecycle events with optional
OpenTelemetry spans, and a reasoning- and agent-linked audit log. A
library you install, not a service you depend on.

```python
from tbay import TbayClient, guarded

client = TbayClient("postgresql://postgres:tbay@localhost:5432/tbay")
# also: "sqlite:///~/.tbay/db.sqlite" or "redis://localhost:6379/0"

@guarded(client, policy="readonly")
def github_search(query: str) -> dict:
    return real_github_api_call(query)

@guarded(client, policy="destructive")
def refund_customer(customer_id: str, amount: float) -> dict:
    return stripe_refund(customer_id, amount)
```

`github_search` now caches and collapses concurrent duplicates;
`refund_customer` never double-runs and pauses for a human before
executing. `@guarded` only wraps a plain callable, so it drops in under
LangChain's `@tool`, the OpenAI Agents SDK's `@function_tool`, CrewAI
tools, an MCP server's tool handlers, or bare functions
([recipes](docs/integrations.md)).

When something goes wrong anyway, you have an emergency brake and a
ceiling on the damage:

```yaml
# policy.yaml: refunds may total at most $1000/day, across every process
policies:
  destructive:
    approval_required: true
    budget: {arg: amount, max: 1000, per: 1d}
```

```
$ tbay pause --reason "agent runaway"    # stop every guarded call, everywhere, now
$ tbay resume
```

Agent frameworks solve planning and orchestration; none of them solve
*execution safety*. Once a tool is selected, nothing stops it from being
called twice, called too often, or fired on a destructive action without
a human in the loop. tbay sits underneath any framework and handles that,
durably, across processes, in whatever database you already run. **Not a
hosted service**: state lives entirely in a database you own; nothing
calls home.

## Install

```
pip install tbay               # SQLite backend, stdlib only
pip install tbay[postgres]     # + Postgres
pip install tbay[redis]        # + Redis

# or: uv add tbay / "tbay[postgres]" / "tbay[redis]"
```

## Documentation

| Guide | What it covers |
|---|---|
| [Quickstart](docs/quickstart.md) | First guarded tool, the dev container, running the demo |
| [Tutorial](examples/tutorial/README.md) | 13 runnable, narrated scripts: every feature, step by step, SQLite-only |
| [Design rationale](docs/design.md) | Why each mechanism works the way it does |
| [Policies](docs/policies.md) | The four risk tiers, the YAML file, every policy field |
| [Caching and idempotency](docs/caching.md) | Idempotency keys, TTL, singleflight, semantic caching, volatile calls, rate limits |
| [Approvals](docs/approvals.md) | Pause/approve flow, signed webhooks, bypass thresholds, signed approvals, rejection reasons |
| [Runtime controls](docs/controls.md) | The kill switch (`tbay pause`), spend budgets, stale-lease crash recovery |
| [Observability](docs/observability.md) | Audit log, lifecycle events, OpenTelemetry, reasoning traces, agent identity, the CLI, the dashboard |
| [Integrations](docs/integrations.md) | LangChain, OpenAI Agents SDK, CrewAI, MCP servers, `guard_tools` |
| [Storage backends](docs/backends.md) | SQLite, Postgres, Redis: guarantees, schema, migrations, clearing data |
| [API reference](docs/api.md) | Every public function and class, with examples |

## Try it in two minutes

Open the repo in VS Code, run "Dev Containers: Reopen in Container"
(bundles Python + Postgres + Redis, nothing to install), then:

```
uv run python dashboard/app.py       # terminal 1: live dashboard on port 8787
uv run python examples/demo.py       # terminal 2: every feature, one run
```

The demo ends blocked on a $500 refund; approve or reject it from the
dashboard and watch the blocked call resume or learn why it was refused.
Details in the [Quickstart](docs/quickstart.md).

## Development

```
uv sync --extra dev
uv run pytest
```

Postgres- and Redis-backed tests need `TBAY_TEST_PG_DSN` /
`TBAY_TEST_REDIS_URL`; CI and the dev container provide both.

## License

MIT
