Routing + ingress + observability hub for Claude Agent SDK agents you self-host.
Project description
🍱 heybento
Claude Code gives your agent a brain. Bento gives it a heart.
Bento is the routing, ingress, history and lifecycle layer for Claude Agent SDK agents you self-host. Claude Code is where you write and reason about an agent. Bento is where it actually lives — webhook URLs that don't change, cron triggers that fire on schedule, an inbox queue with claim/retry, sessions you can replay weeks later.
Single-tenant, self-host on your own VPS. No SaaS. See ADR-0002 for the design.
What Bento gives you
- One stable ingress URL per agent. Point Microsoft Graph, Slack,
GitHub, whatever your webhook source is, at
https://bento.example.com/agents/agt_xyz/inbox/...and never touch it again — whether the agent is running on your laptop, your VPS, or Fly.io. - Cron that tikt without your agent needing to run an internal scheduler. The hub fires; the agent picks up the event.
- An inbox queue. Items wait while the agent is offline; they get claimed and processed when it comes back.
- Local-dev priority. Run
bento devon your laptop and the hub routes events to your terminal — the hosted agent (if any) is bypassed automatically until you quit, then it picks up the queue. - Sessions, events, cost. Every run captured, replayable, with token + cost breakdown.
- Encrypted secrets (Fernet at rest), runtime config overrides via env vars, GitHub-connected deploys with manual ‘Deploy’ button.
Install
pip install heybento
# or: uv tool install heybento
Provides one CLI: bento.
Quick start: run the hub locally
bento hub # http://localhost:8000
The hub is FastAPI + SQLite (~/.bento/bento.db). It looks for
~/.bento/.env on startup so you can keep your config + tokens in one
place.
Quick start: write and run an agent
bento new melvin --project noise --description "NOISE assistant"
cd melvin
bento dev
bento new scaffolds agent.py + README.md. bento dev registers
the agent with the hub, opens the agent's detail page in your browser,
spawns the agent as a local subprocess and reloads it on every save.
Events from the hub flow to your terminal.
A minimal agent.py:
import os
import bento
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage
app = bento.App(name="melvin", project="noise")
@app.cron("0 9 * * 1", description="Weekly Monday review")
async def monday_review(payload: dict):
await app.log("monday-review-start")
# … do work, possibly call app.query(...) …
return "done"
@app.webhook("teams", description="Inbound Teams message")
async def on_teams(payload: dict):
options = ClaudeAgentOptions(
system_prompt="Reply concisely.",
max_turns=int(os.getenv("BENTO_MAX_TURNS", "3")),
allowed_tools=[],
)
async for msg in app.query(prompt=payload["text"], options=options):
if isinstance(msg, ResultMessage):
return msg.result or ""
return ""
Deploy paths
Bento-hosted (Docker on your VPS). Push your agent to GitHub
(private repo is fine). In the agent's detail page → Source: paste
owner/repo, branch, click Deploy. Bento clones the repo into
~/.bento/deploys/<agent_id>/ and starts a container from the
bento-agent-runtime image with the clone mounted read-only.
Requires BENTO_GITHUB_TOKEN on the hub (fine-grained PAT scoped to
the relevant repos, read-only). Token stays in the hub process, never
in any agent container.
Anywhere else (Fly, Railway, Render, your own Kubernetes). Bento
doesn't manage the runtime there, but the agent still talks to your
hub via HTTPS. Pin BENTO_HUB to your hub URL, set BENTO_AGENT_ID
after first registration, and you keep the ingress URL, inbox, cron,
session history, and dev-priority routing. The hub UI shows the agent
as external — Deploy/Restart buttons are no-ops, everything else
works.
Environment variables
| Var | Where | Purpose |
|---|---|---|
BENTO_HUB |
SDK side | URL of your hub (http://localhost:8000 locally) |
BENTO_DB |
hub | SQLite path (default ~/.bento/bento.db) |
BENTO_DEPLOYS |
hub | git-clone root (default ~/.bento/deploys) |
BENTO_GITHUB_TOKEN |
hub | PAT for cloning private repos |
BENTO_SECRET_KEY |
hub | Fernet key (auto-generated at ~/.bento/master.key if absent) |
BENTO_AUTOSPAWN |
hub | 1 enables the supervisor's Docker spawn path (production VPS) |
BENTO_AGENT_ID |
SDK | Anchor re-registers to this row regardless of agent rename |
Status
Pre-1.0. Working on agent-builder branch. Single-tenant self-host only — no multi-tenant SaaS planned. Open-source release is on the roadmap once the dev loop is stable enough that real-world agents are running on it (currently dogfooded with the NOISE assistant).
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
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 heybento-0.1.0.tar.gz.
File metadata
- Download URL: heybento-0.1.0.tar.gz
- Upload date:
- Size: 2.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15d52ceb864dbd4a07a27900a8af4f7f74303a3417db5dedbb0c70549777b934
|
|
| MD5 |
62fdc108ebbc82516f7cb5cd95e292fd
|
|
| BLAKE2b-256 |
70f2955ae6be9d9b698b8a832216af0b72c31f61367f5323a317d122ef26c9f5
|
File details
Details for the file heybento-0.1.0-py3-none-any.whl.
File metadata
- Download URL: heybento-0.1.0-py3-none-any.whl
- Upload date:
- Size: 1.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e542e8be9f34eb2a6258211714d89ae612b530d7e91539769da89125272c6a2
|
|
| MD5 |
6e0229b6b6587c3e06543911c6a37666
|
|
| BLAKE2b-256 |
c04f07d0800baf26d88e4f786416d6981ee5855da1fe5ae48e6c0c23de6fd61d
|