---
title: Build an agentic app in FastAPI with OpenAI Agents API and Vercel Sandbox
description: Learn how to build a repository Q&A app using FastAPI, OpenAI Agents API, and Vercel Sandbox, with isolated code inspection, streamed progress, downloadable evidence, and deployment to Vercel.
url: /kb/guide/fastapi-openai-agents-api-vercel-sandbox
canonical_url: "https://vercel.com/kb/guide/fastapi-openai-agents-api-vercel-sandbox"
published: 2026-09-11
last_updated: 2026-09-11
authors: Anshuman Bhardwaj
related:
  - /docs/sandbox
  - /docs/agent-resources/vercel-plugin
  - /docs/cli
  - /docs/sandbox/python-sdk-reference
  - /docs/sandbox/concepts/authentication
  - /docs/frameworks/backend/fastapi
  - /kb/guide/openai-agents-api-vercel
  - /kb/guide/v0-clone-openai-agents-vercel-sandbox
  - /docs/sandbox/concepts/persistent-sandboxes
  - /kb/guide/run-claude-managed-agent-tools-with-vercel-sandbox
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

This FastAPI template answers questions about public GitHub repositories using OpenAI Agents API and [Vercel Sandbox](https://vercel.com/docs/sandbox). The OpenAI Agents API lets you create agent sessions, submit tasks, and stream progress as the agent works. This template uses the OpenAI Agents API through its Python SDK.

Vercel Sandbox provides Linux microVMs that you can create and manage from your application. A sandbox provides an agent with an isolated environment in which it can read files and run commands.

A user supplies a repository, a Git ref, and a question such as “What framework and package manager does this project use?” The app clones the repository into a sandbox, lets the agent inspect it, and returns an answer with supporting evidence.

In this guide, you'll connect an OpenAI Agents API session to Vercel Sandbox, run the template locally, and deploy the FastAPI app to Vercel.

Deploy the template now, or follow the steps below to build it.

## Quick start with an AI coding agent

### Agent prompt

```txt
Help me set up and deploy the repository agent from https://github.com/vercel-labs/openai-agents-api-fastapi. Read README.md, AGENTS.md, ARCHITECTURE.md, and .env.example before making changes.

Use Python 3.11 or later and a virtual environment. Install the dependencies listed in requirements.txt and requirements-dev.txt. Read the [OpenAI Agents API public beta SDK docs](https://developers.openai.com/api/docs/guides/agents-api/overview) before implementing or making suggestions.

Help me configure OPENAI_API_KEY and a separate restricted OPENAI_EXECUTOR_API_KEY using the documented permissions. The application defines its agent inline for each session; no AGENT_ID is needed. Explain how to obtain missing credentials without putting secrets in chat or tracked files.

Link a Vercel project with Sandbox access and run vercel env pull .env.local for local authentication. Follow the README to start FastAPI locally. Preserve the bounded repository inspection, separation of application and executor keys, and cleanup of sessions and sandboxes.

Run the existing tests and lint checks. Check /api/health, then submit a focused question about a public GitHub repository with a valid ref. Verify the answer, session and sandbox IDs, and RESULT.md, evidence.json, and events.jsonl downloads.

Configure both OpenAI keys in Vercel, deploy a preview, and repeat the verification. Report the deployment URL and any remaining setup requirements.
```

This guide covers the core implementation. The AI assistant prompt above covers all the details your coding agent needs, and you can see the full implementation in the [template repository](https://github.com/vercel-labs/openai-agents-api-fastapi).

### Vercel Plugin

Optionally, install the [Vercel Plugin](https://vercel.com/docs/agent-resources/vercel-plugin) for Vercel-specific guidance in your coding agent. It provides product context, skills, and commands for working with Vercel, including Vercel Sandboxes and deployments.

```bash
npx plugins add vercel/vercel-plugin
```

## Prerequisites

Before you begin, make sure you have:

- Python 3.11 or later and Git installed.
  
- Node.js and npm to install the [Vercel CLI](https://vercel.com/docs/cli): `npm install -g vercel`.
  
- A [Vercel account](https://vercel.com) and a project with Sandbox access.
  
- An OpenAI organization and project. You'll create separate application and executor keys during local setup.
  
- A public GitHub repository to inspect.
  

## How it works

The app is a single FastAPI project that serves the browser interface and handles each inspection through `POST /api/inspect`:

1. FastAPI validates the repository URL, Git ref, and question, then creates a self-hosted Agents API session.
   
2. The Vercel Sandbox SDK creates a sandbox and clones the selected repository into `/vercel/sandbox`.
   
3. The app installs Codex in the sandbox and starts `codex exec-server`. The executor connects outbound to the OpenAI Agents API using the session's environment ID.
   
4. FastAPI submits the question and streams progress and available answer text to the browser using server-sent events.
   
5. The agent writes an answer and structured evidence. FastAPI collects the files, deletes the API session while the executor is connected, stops the sandbox, and returns the result.
   

```plaintext
Browser → FastAPI → Agents API session
             │              ↕
             └────→ Vercel Sandbox
                      Codex executor + cloned repository
```

Each question gets its own session and sandbox. The prompt asks the agent to use at most eight short commands, leave the checkout unchanged, and avoid dependency installation, builds, and network requests during inspection. The sandbox's network policy separately limits outbound connections to the services needed for cloning, installing Codex, and connecting the executor.

The result includes three downloads: `RESULT.md` for the answer, `evidence.json` for inspected files, commands, and limitations, and `events.jsonl` for API events captured by FastAPI. The app keeps these in the response rather than saving them to a database.

## Steps

### 1\. Set up the project

Clone the [template repository](https://github.com/vercel-labs/openai-agents-api-fastapi) and install its dependencies in a virtual environment:

```bash
git clone https://github.com/vercel-labs/openai-agents-api-fastapi.git
cd openai-agents-api-fastapi
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt -r requirements-dev.txt
```

On Windows, activate the environment with `.venv\Scripts\Activate.ps1` in PowerShell.

The template already includes the complete application. The application is organized into these files:

| File                              | Purpose                                                   |
| --------------------------------- | --------------------------------------------------------- |
| `sandbox_agent/main.py`           | Serves the page and inspection endpoint                   |
| `sandbox_agent/runner.py`         | Creates sessions, streams events, and cleans up resources |
| `sandbox_agent/vercel_sandbox.py` | Creates the sandbox and starts the executor               |
| `sandbox_agent/prompt.py`         | Defines the inspection instructions and output files      |
| `sandbox_agent/artifacts.py`      | Collects the answer, evidence, and event log              |
| `app.py`                          | Exports the application for Vercel                        |

### 2\. Integrate OpenAI Agents API

In `sandbox_agent/runner.py`, the session setup follows this pattern inside the asynchronous inspection handler:

```python
from openai import AsyncOpenAI

from sandbox_agent.config import get_settings
from sandbox_agent.prompt import build_agent_instructions

# Inside the asynchronous inspection handler.
settings = get_settings()
client = AsyncOpenAI(
    api_key=settings.openai_api_key,
    base_url=settings.agents_api_url,
    max_retries=0,
    timeout=settings.session_create_timeout_seconds,
)

session = await client.beta.agents.sessions.create(
    agent={
        "model": settings.agent_model,
        "instructions": build_agent_instructions(),
        "reasoning": {"effort": settings.agent_reasoning_effort},
        "text": {"verbosity": "low"},
    },
    environment={
        "type": "self_hosted",
        "workspace_directory": "/vercel/sandbox",
    },
)

environment = session.environment
if environment.type != "self_hosted":
    raise RuntimeError(
        f"Expected self-hosted environment, got {environment.type}"
    )

environment_id = environment.id
remote_url = environment.remote_url
```

The environment ID connects this session to the executor you'll start in the next step. It is separate from both the Agents API session ID and the Vercel Sandbox ID.

`settings.agents_api_url` defaults to `https://api.openai.com/v1`, while `remote_url` comes from the session response and must remain unchanged.

`build_agent_instructions()` defines the agent's role and tells it to treat repository contents as evidence, never as instructions. `build_inspection_prompt()` adds the user's question, the command budget, and the required output paths under `/tmp/sandbox-agent`.

Inside the inspection handler, build the prompt from the validated request:

```python
from sandbox_agent.prompt import build_inspection_prompt

prompt = build_inspection_prompt(
    repo_url=request.repo_url,
    ref=request.ref,
    question=request.question,
)
```

Here, `request` is the validated inspection request containing the repository URL, Git ref, and question. The resulting `prompt` is what the later `input=prompt` sends to the agent.

Once the sandbox executor has started, submit the prompt through `client.beta.agents.sessions.stream(session.id, input=prompt)` as an async context manager. This opens the stream before sending the input:

```python
from sandbox_agent.sse import encode_sse

text_parts = {}

async with client.beta.agents.sessions.stream(
    session.id,
    input=prompt,
    timeout=settings.stream_no_progress_timeout_seconds,
) as events:
    async for event in events:
        if event.type == "agent.session.turn.output_text.delta":
            key = (event.item_id, event.output_index, event.content_index)
            text_parts[key] = text_parts.get(key, "") + event.delta
            yield encode_sse("answer_delta", {"delta": event.delta})
        elif event.type == "agent.session.turn.output_text.done":
            key = (event.item_id, event.output_index, event.content_index)
            text_parts[key] = event.text

streamed_answer = "".join(text_parts.values())
```

`output_text.done` events replace the matching content part because deltas may be absent. The complete handler also captures events, checks executor health while opening and consuming the stream, handles failures, and collects artifacts. It requires a completed root-agent turn and a final idle session with no run error before reporting success.

By default, the handler stops waiting after 45 seconds without an event or when the inspection reaches its 150-second limit. The final answer is read from `RESULT.md` when available, with streamed text as a fallback.

### 3\. Integrate managed compute with the Sandbox SDK

The template uses the Python Sandbox SDK included in the `vercel` package. In `sandbox_agent/vercel_sandbox.py`, create a sandbox from the validated repository URL and Git ref:

```python
from vercel.sandbox import AsyncSandbox, GitSource, NetworkPolicyCustom

sandbox = await AsyncSandbox.create(
    source=GitSource(url=repo_url, revision=ref, depth=1),
    runtime="node24",
    timeout=settings.sandbox_timeout_ms,
    network_policy=NetworkPolicyCustom(
        allow=list(settings.sandbox_allowed_domains)
    ),
)
```

`GitSource` prepares the checkout in `/vercel/sandbox`. The Node.js runtime supplies npm so the app can install Codex inside the sandbox:

```python
install = await sandbox.run_command(
    "npm",
    ["install", "-g", settings.codex_package],
    sudo=True,
)
if install.exit_code != 0:
    raise RuntimeError("Codex installation failed")
```

The default package is `@openai/codex@alpha`. The app also creates `/tmp/sandbox-agent` for output files and writes the inspection prompt there.

Start the executor as a detached command, passing the environment ID returned by the Agents API:

```python
executor = await sandbox.run_command_detached(
    "codex",
    [
        "exec-server",
        "--remote",
        remote_url,
        "--environment-id",
        environment_id,
    ],
    cwd="/vercel/sandbox",
    env={"CODEX_API_KEY": executor_api_key},
)
```

The executor receives a restricted OpenAI key, while the application key stays in FastAPI. Because the executor connects outbound, this integration does not need an exposed sandbox port.

In `sandbox_agent/runner.py`, pass the session's environment values and restricted executor key to `start_sandbox`:

```python
from sandbox_agent.vercel_sandbox import start_sandbox

handle = await start_sandbox(
    executor_api_key=settings.openai_executor_api_key,
    environment_id=session.environment.id,
    remote_url=session.environment.remote_url,
    repo_url=request.repo_url,
    ref=request.ref,
    prompt=prompt,
    settings=settings,
)
```

After collecting the output, delete the session while the executor is connected, stop the sandbox, and close the OpenAI client. These calls show the cleanup order:

```python
await client.beta.agents.sessions.delete(session.id)
await sandbox.stop(blocking=True)
await client.close()
```

The full runner wraps each operation in separate error handling so a failure does not prevent the remaining cleanup attempts. It deletes the session first because stopping the sandbox can move the session into `requires_action` and block deletion.

Each operation has a separate timeout, and transient session-deletion conflicts are retried within that timeout. Cleanup is shielded from browser-disconnect cancellation, and unfinished work is canceled with an `agent.session.input.cancel` event before cleanup. Deleting the API session alone does not stop the Vercel Sandbox.

See the [Python Sandbox SDK reference](https://vercel.com/docs/sandbox/python-sdk-reference) when upgrading, since newer SDK versions may use different methods and lifecycle options.

## Set up locally

### Configure credentials

Copy the environment template:

```bash
cp .env.example .env
```

Create two OpenAI API keys under the same organization, project, and user or service account:

| Variable                  | Purpose                                       | Required access                                                                         |
| ------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------- |
| `OPENAI_API_KEY`          | Creates and manages sessions from FastAPI     | An application key with Agents API access; follow the SDK's application-key permissions |
| `OPENAI_EXECUTOR_API_KEY` | Connects the executor from inside the sandbox | A separate restricted key from the OpenAI dashboard > Create Environment key flow       |

The [Agents API quickstart](https://developers.openai.com/api/docs/guides/agents-api/quickstart) describes application-key permissions. Create the executor key in the Agents dashboard, following the [self-hosted environment authentication instructions](https://developers.openai.com/api/docs/guides/agents-api/environments/self-hosted#authentication).

Add both values to `.env`:

```dotenv
# Application key: keep outside the sandbox.
OPENAI_API_KEY=your_application_key

# Restricted environment key: same organization, project, and owner.
OPENAI_EXECUTOR_API_KEY=your_executor_key
```

Next, authenticate with Vercel and link the project from the repository root:

```bash
vercel login
vercel link
vercel env pull .env.local
```

The last command writes a development `VERCEL_OIDC_TOKEN` to `.env.local`. The Sandbox SDK uses it to authenticate local requests; refresh it by running the same command again if it expires. To learn more, see [Sandbox authentication](https://vercel.com/docs/sandbox/concepts/authentication).

The app loads `.env.local` before `.env`, without overriding existing environment variables. Keep the OpenAI keys in `.env` and the Vercel token in `.env.local`; remove duplicate blank entries in `.env.local` if they mask your keys. Both files are ignored by Git.

### Run the app

With the virtual environment active, start FastAPI:

```bash
vercel dev
```

Open `localhost:3000`, enter a public GitHub repository and a valid ref, and ask a focused question:

> What framework and package manager does this repository use? Cite the files that support your answer.

A completed inspection shows the answer, evidence, model, session ID, sandbox ID, duration, and artifact downloads. Review `evidence.json` for limitations and `events.jsonl` for the captured API events.

You can check configuration at `localhost:3000/api/health`. A `ready` response confirms that the required OpenAI settings are present and distinct; submit an inspection to verify the credentials and service connections. If an inspection times out, try a narrower question.

### Deploy to Vercel

Add both OpenAI keys to the linked Vercel project:

```bash
vercel env add OPENAI_API_KEY
vercel env add OPENAI_EXECUTOR_API_KEY
```

Select **Preview** and **Production** when prompted so both deployment environments can run inspections. Then create a preview deployment from the repository root:

```bash
vercel deploy
```

Vercel automatically detects the project’s framework and deploys the app correctly. To learn more about FastAPI deployments, see [FastAPI on Vercel](https://vercel.com/docs/frameworks/backend/fastapi).

The template exports the FastAPI app through `app.py`:

```python
from sandbox_agent.main import app
```

Open the preview URL, check `/api/health`, and submit a small repository question. Confirm that the answer and downloads appear and that the result includes both session and sandbox IDs. Once you've verified the preview, deploy to production:

```bash
vercel deploy --prod
```

## Next steps

Use the working template as a starting point for a more specific repository assistant:

- **Change the inspection task.** Adapt `sandbox_agent/prompt.py` to explain a repository's test setup, trace a request through source files, or identify dependencies relevant to a planned migration.
  
- **Keep reports between visits.** Add storage for the answer, evidence, and event log so users can revisit or compare inspections.
  
- **Support longer jobs.** Move session and sandbox management into a background worker before adding migrations, builds, or multiple turns. The current app ties each run to one browser request and does not resume disconnected runs.
  
- **Explore the APIs.** Read the [Agents API SDK guide](https://developers.openai.com/api/docs/guides/agents/sdk) for session and event handling, and the [Vercel Sandbox documentation](https://vercel.com/docs/sandbox) for execution environments and lifecycle options.
  

## Related resources

- [Build an agent with OpenAI Agents API on Vercel.](https://vercel.com/kb/guide/openai-agents-api-vercel)
  
- [Build a v0-style app builder with OpenAI Agents API and Vercel Sandbox.](https://vercel.com/kb/guide/v0-clone-openai-agents-vercel-sandbox)
  
- Read the [OpenAI Agents API docs.](https://developers.openai.com/api/docs/guides/agents-api/overview)
  
- Follow the [Python SDK setup documentation](https://github.com/openai/openai-agents-python).
  
- Clone and review the [template repository.](https://github.com/vercel-labs/openai-agents-api-fastapi)
  
- Read about [Vercel Sandbox persistence.](https://vercel.com/docs/sandbox/concepts/persistent-sandboxes)
  
- Learn more about the Vercel Sandbox APIs with the [Python SDK Reference.](https://vercel.com/docs/sandbox/python-sdk-reference)
  
- Learn how to [Build a Claude Managed Agent with Vercel Sandbox.](https://vercel.com/kb/guide/run-claude-managed-agent-tools-with-vercel-sandbox)