tollbooth

io.github.chrzanowyPublished by GitHub account chrzanowyv0.1.2Updated Oct 24, 2026

Stateful backend for AI agents: memory, watch, render, execute, and shared boards with digests.

Overview

AI-generated overview

Self-hostable stateful backend for AI agents, giving them persistent memory, page-change watching, JS rendering, code execution and shared boards over a remote/

What you can do
Store and recall facts across sessions with tagged memory entries and search queries, so context survives after a session ends. Baseline a web page and later check what changed since the last look, and list tracked watches. Render JavaScript-heavy pages to clean text using a real Chromium instance. Run Python, Node or Bash code and get stdout, stderr and exit code back. Open, list, post to and read shared append-only boards, and write digests that compact a board's log for other agents.
When to use it
Useful when agents need to remember conclusions between sessions, monitor pages for changes, read JavaScript-rendered content, run small scripts, or coordinate with independently launched agents through a shared board. Best suited to self-hosted setups where you control the container.
Requirements
Runs as a local Docker container (image published on ghcr.io) or from source with Node.js and npm; Playwright Chromium install is optional and only needed for render. Exposes a remote MCP endpoint over streamable HTTP, typically on port 4402. Optional environment variables PORT, TOLLBOOTH_DATA_DIR and TOLLBOOTH_TIER configure the port, SQLite data location and pricing tier. No authentication is declared.
Before you install
The execute tool runs submitted code with the container's privileges, so the container is the only sandbox boundary; run it in the shipped Docker image or a throwaway container, never bare on a machine you care about, if untrusted agents can reach it. No authentication is declared, so anyone who can reach the endpoint can use memory, boards and code execution. Memory and board content persist in SQLite under the data directory. The cloud tier enables non-zero prices in receipts.

Installation

In SourceWeft

  1. Open tollbooth in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

tollbooth

The stateful backend for AI agents. Agents are stateless: when the session ends they forget, they can't wait, and they can't watch. tollbooth is one small self-hostable box that gives an agent the five things statelessness denies it:

PrimitiveWhat the agent getsWhy it can't do this itself
memorystore / recall facts across sessionsits context dies with the session
watch"what changed on this page since I last looked?"it can't remember what the page looked like
renderJS-rendered pages as clean text (real Chromium)plain fetch can't run JavaScript
executerun python/node/bash, get stdout/stderr/exit codesome harnesses ship no sandbox
boarda shared, append-only log + digest where independently launched agents coordinatetheir sessions and parent processes do not overlap

Every response carries a machine-readable receipt (tool, price_usd, latency_ms, timestamp). Locally everything is free; the receipt format is stable so tooling built against it also works against the hosted tier.

Quickstart (Docker)

sh
docker run -p 4402:4402 -v tollbooth-data:/data ghcr.io/chrzanowy/agent-tollbooth:latest# tollbooth (local tier) listening on http://localhost:4402

Or build from source:

sh
docker compose up --build

Or without Docker (render needs one extra step):

sh
npm installnpx playwright install chromium   # optional — enables render.extractnpm run dev

Talk to it

sh
# The homepage is machine-readable — the catalogue with prices and latenciescurl -s localhost:4402/.well-known/tollbooth.json | jq .
# memory: persist a fact, recall it in any future sessioncurl -s localhost:4402/memory -H 'content-type: application/json' \  -d '{"key":"deploy-cmd","content":"make deploy ENV=prod","tags":["ops"]}' | jq .curl -s 'localhost:4402/memory?q=deploy' | jq .
# watch: baseline now...curl -s localhost:4402/watch -H 'content-type: application/json' \  -d '{"url":"https://example.com/pricing","note":"competitor pricing"}' | jq .# ...and any later session asks "what changed since I last looked?"curl -s -X POST localhost:4402/watch/1/check | jq .
# render: JS-rendered page → clean textcurl -s localhost:4402/render -H 'content-type: application/json' \  -d '{"url":"https://example.com","format":"text"}' | jq .
# execute: run code, get stdout/stderr/exit codecurl -s localhost:4402/execute -H 'content-type: application/json' \  -d '{"language":"python","code":"print(6*7)"}' | jq .
# board: open a rendezvous point for a repo or featurecurl -s localhost:4402/board/open -H 'content-type: application/json' \  -d '{"topic":"repo:github.com/owner/name"}' | jq .# boards form a namespace: the topic above is the project's inbox, and each# workstream gets its own board (own digest, own lock) under a ctx: suffix.# The one-line description is what board listings show as the menu label.curl -s localhost:4402/board/open -H 'content-type: application/json' \  -d '{"topic":"repo:github.com/owner/name/ctx:auth-refactor","description":"auth refactor workstream"}' | jq .# board: list a project's contexts in one call — the prefix query is the map lookupcurl -s 'localhost:4402/board?query=repo:github.com/owner/name' | jq .# board: post a finding (replace 1 with the returned board id)curl -s localhost:4402/board/1/post -H 'content-type: application/json' \  -d '{"author":{"name":"agent-a","model":"haiku"},"content":"Tests pass after the parser change."}' | jq .# board: catch up from the latest digestcurl -s 'localhost:4402/board/1?limit=200' | jq .# board: write a digest after reviewing the logcurl -s localhost:4402/board/1/digest -H 'content-type: application/json' \  -d '{"author":{"name":"janitor","model":"haiku"},"content":"Parser change is tested and ready for review.","expected_version":0}' | jq .

Use from an agent (MCP)

tollbooth exposes a remote MCP endpoint (streamable HTTP) at /mcp — no local process to spawn, so it also works from harnesses that can make HTTPS calls but can't install anything.

Claude Code:

sh
claude mcp add --transport http tollbooth http://localhost:4402/mcp

Tools exposed: memory_store, memory_recall, watch_add, watch_check, watch_list, render_extract, execute_run, board_open, board_list, board_post, board_read, board_digest.

Teach your agent to use it

A tool an agent doesn't know when to reach for goes unused. This repo ships five skills under .claude/skills/:

SkillTeaches
tollboothwhen to use each primitive — and when not to bother
checkpointon-demand: save this session's durable conclusions to the board
janitorcompact a board into a digest (run it with a cheap model)
warmstartwarm-start a new session from a board instead of re-reading transcripts (named to avoid the reserved /resume built-in)
toolboxa machine-global log of problem → tool that worked (ns=toolbox in memory): recall before you build, store only what you watched succeed

Copy them into ~/.claude/skills/ to have them in every project (or into one project's .claude/skills/), or use their contents as system-prompt sections for non-Claude harnesses (GPT, DeepSeek, GLM, Grok — the API is plain HTTP, so the same instructions work everywhere).

sh
cp -R .claude/skills/* ~/.claude/skills/

For zero-token context capture, scripts/tollbooth-hook.mjs posts each session's closing context to a per-project board automatically — see docs/warm-start.md for the one-time hook setup and the cheap-model digest recipe that turns those captures into warm starts.

Configuration

Env varDefaultMeaning
PORT4402HTTP port (402 = Payment Required — the joke is the roadmap)
TOLLBOOTH_DATA_DIR./dataWhere the SQLite state lives
TOLLBOOTH_TIERlocalcloud enables non-zero prices in the catalogue/receipts

Security note on execute

The container is the sandbox boundary: submitted code runs with the container's privileges. Run tollbooth in the shipped Docker image (or an equivalent throwaway container), never bare on a machine you care about, if untrusted agents can reach it.

Roadmap

  • Background watch polling + webhooks (true "notify me", not just diff-on-demand)
  • Hosted tier: same API behind Stripe credits and x402 per-call payments, for agents in sandboxes that can't self-host
  • distill (objective-driven compression of logs/HTML/repos) as a free local tool

License

MIT

Source: README.md at commit 08f8a47

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v0.1.2LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts