examples/frameworks/. Each one is a one-file adapter with a README, its own dependencies, and an offline check that runs in CI without model calls or API keys.
Two ways in
A module agent: JavaScript and TypeScript
The adapter is a JS or TS module that default-exports anAgentAdapter. sandtable passes createSession its default system prompt and the domain’s tools as JSON schemas, and passes each reply a callTool function. callTool is a plain async function, so the framework’s tool can call it directly:
The HTTP step protocol: any language
A service in any language can speak the HTTP step protocol: sandtable POSTs a user message, the service answers with a reply or with tool calls, and sandtable POSTs the results of those calls back. Most frameworks run the tool loop in-process and expect a tool function to return a value. The Pipecat and LiveKit Agents adapters bridge the two by suspending the framework’s tool call: the tool function waits, the pending call goes back to sandtable astool_calls, and when sandtable posts tool_results, the waiting call returns the result and the framework’s loop carries on until it replies or calls another tool.
session_id. The service is not told when a trial ends.
Vercel AI SDK
The adapter wraps aToolLoopAgent. Each domain tool becomes a dynamicTool with the tool’s JSON schema, and a failed call throws, so the AI SDK hands the error to the model as a tool error:
ModelMessage[] history and appends each turn’s responseMessages. The offline check drives the adapter with the AI SDK’s MockLanguageModelV4 and runs a freight task end to end with the scripted caller. Example and README.
OpenAI Agents SDK
The adapter wraps anAgent and a Runner. Each domain tool becomes a function tool with the tool’s JSON schema as its parameters:
- Strict mode, the SDK’s default, works with sandtable’s schemas: the SDK sends optional parameters as nullable and drops the nulls before
execute. - Return a failed call’s error as output. A thrown error reaches the model only as the SDK’s generic error message.
- The session passes the Runner’s
result.historyback in as the next turn’s input.
ScriptedModel and runs a freight task end to end with the scripted caller. Example and README.
Claude Agent SDK
The adapter runs onequery() per session in streaming input mode, so the SDK keeps the conversation, and serves the domain’s tools from an in-process MCP server whose handlers call callTool. Claude Code’s built-in tools are turned off, so the only tools the agent has are the simulated world’s:
Pipecat
Pipecat is a voice framework. sandtable rehearses the LLM-and-tools layer as text: what the agent says and which tools it calls. It does not rehearse audio, turn-taking or latency. The example serves the HTTP step protocol from Python and suspends Pipecat’s tool calls until sandtable posts the results. Example and README.LiveKit Agents
LiveKit Agents is a voice framework too, and the same limits apply: sandtable rehearses the LLM-and-tools layer as text, not audio, turn-taking or latency. The example serves the HTTP step protocol from Python and suspends the agent’s tool calls until sandtable posts the results. Example and README.Plain HTTP service
A framework-free Python service on the Anthropic Messages API: it keeps each session’s messages, returns Claude’stool_use blocks as tool_calls, and sends sandtable’s results back to Claude as tool_result blocks. Start here if your agent is your own loop. Example and README.
Run the offline checks
The TypeScript examples importsandtable-ai from this repository ("sandtable-ai": "file:../../.."), so they check the code next to them. Build the root first. They need Node 22.18 or later. In your own project, install sandtable-ai from npm instead.