Review pull requests in a sandbox you own

Composio usually runs your tools for you. A local sandbox is for the times you need to run them yourself: your filesystem, your shell, your security boundary. You still get managed auth and 1000+ apps; you just keep the code execution.

This example builds a GitHub PR reviewer that does exactly that: it clones a pull request into a sandbox you own, runs the repo's real checks there, and posts one grounded comment. The sandbox here is E2B, but E2B is just the sample. The same pattern works with your own VM, container, Kubernetes job, or internal sandbox service.

It comes down to a handful of Composio pieces:

  1. A local sandbox session is a Composio session with code execution turned off. Composio still does discovery and auth; it just won't run code for you.
  2. The helper contract is what comes back: a Python helper exposing the same run_composio_tool, invoke_llm, and web_search tools Composio's managed sandbox runs for you, plus the env it needs. You inject it into your sandbox and the agent calls it.
  3. Your sandbox is the boundary. Tool execution happens in a box you control. E2B is the replaceable sample runner; the contract it honors is the real interface.

The sandbox holds your project API key

The env that experimental_createLocalWorkbenchSession returns includes your project COMPOSIO_API_KEY, and you inject that env into the sandbox. Anything running there can read it, including the untrusted PR code you clone and build. Treat the sandbox as your trust boundary: run it on infrastructure you control, give the reviewer a key scoped to only what it needs, and rotate the key if a run could have leaked it.

local-sandbox.runtimecode runs in your box
Host
Your orchestrator
src/runner.ts

Creates the session with workbench.enable: false, then starts a sandbox you own.

helper + env sandbox

Sandbox · yours
Reviewer agent
your filesystem + shell

Clones the PR, installs deps, runs the repo's real checks, all inside your boundary.

run_composio_tool Composio

Composio
Session

Resolves the right GitHub action, runs it under the user's connection, and returns the result to the sandbox.

  • · search + schema discovery
  • · managed GitHub auth
  • · tool execution + result
host (session, execution off) your sandbox (runs checks) run_composio_tool Composio (resolve + execute) grounded PR comment

Below you build the host orchestration from scratch: a bare client first, then a piece at a time up to the full run loop, then a browse of the real source. You bring a Composio API key and a place to run code. Composio brings the tools.

Setup

You need a Composio API key, an OpenAI API key for the reviewer agent, a GitHub connection for your COMPOSIO_USER_ID, and Bun.

bun add @composio/core e2b @openai/agents

Connect GitHub once for the user id you'll review as, then keep that same id for the review run:

bun run connect

Build the host

src/runner.ts is the host: it owns orchestration, never tool execution. It starts as a bare Composio client and grows into the full run loop, one concept at a time. Each diff below is exactly what that concept adds.

Create the Composio client

The whole thing acts as one stable user, against the connections they own. Start there.

Check the GitHub connection

A local sandbox still leans on Composio for auth and tool discovery; only code execution moves to your side. So before booting any infrastructure, confirm this user actually has GitHub connected, and hand them a connect link if not.

Create the local sandbox session

The core of the integration. You create a Composio session yourself with code execution off (workbench.enable: false, so Composio will not run code for you), then hand that session to experimental_createLocalWorkbenchSession. The helper validates the session is local (it errors if the session has the remote workbench enabled, because the managed workbench and a local sandbox can't both run for one session) and returns the pieces you run yourself: a helperSource (a Python helper with run_composio_tool, invoke_llm, and web_search) and the env that helper needs to reach Composio from inside your box.

Start your sandbox, inject the helper

Boot a box you control, write helperSource into it as composio_helper.py, and pass env to the process. That helper is the only Composio-specific thing your sandbox has to carry. E2B is the sample runner; swap it for anything that honors the same contract.

Run the reviewer and stream output

Run the agent inside the sandbox and stream its output back. Whenever the agent calls run_composio_tool, the helper routes that GitHub action back through Composio under this user's connection. Tool execution happens in your box; discovery and auth stay managed.

The whole project

The file above is the spine. The real project rounds it out with a CLI, a smoke/dry-run path, the E2B runner behind the sandbox contract, the reviewer agent and its review policy, and the composio_helper.py the helper source compiles to. Here's a slice of the actual source, with the Composio touch-points highlighted. Browse the tree, read the files:

a slice of the real project, the Composio files do the work

The complete project lives on GitHub: local-pr-reviewer.

Run it

Dry-run first to validate your input with no credentials, network calls, or sandbox startup, then run it for real:

bun run review -- --repo ComposioHQ/composio --pr 123 --dry-run
bun run review -- --repo ComposioHQ/composio --pr 123

The host opens a local sandbox session, boots the sandbox, and runs the repo's real checks inside it, then posts one grounded comment, or nothing if it can't build the PR.