Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
shared/managed-agents-environments.md
1# Managed Agents — Environments & Resources23## Environments45Creating a session requires an `environment_id`. Environments are **reusable configuration templates** for spinning up containers in Anthropic's infrastructure — you might create different environments for different use cases (e.g. data visualization vs web development, with different package sets). Anthropic handles scaling, container lifecycle, and work orchestration.67**Environment names must be unique.** Creating an environment with an existing name returns 409.89### Networking1011| Network Policy | Description |12| ---------------- | ------------------------------------------------------------- |13| `unrestricted` | Full egress (except legal blocklist) |14| `limited` | Deny-by-default; opt in via `allowed_hosts` / `allow_package_managers` / `allow_mcp_servers` |1516```json17{18"networking": {19"type": "limited",20"allow_package_managers": true,21"allow_mcp_servers": true,22"allowed_hosts": ["api.example.com"]23}24}25```2627All three `limited` fields are optional. `allow_package_managers` (default `false`) permits PyPI/npm/etc.; `allow_mcp_servers` (default `false`) permits the agent's configured MCP server endpoints without listing them in `allowed_hosts`.2829**MCP caveat:** Under `limited` networking, either set `allow_mcp_servers: true` or add each MCP server domain to `allowed_hosts`. Otherwise the container can't reach them and tools silently fail.3031### Creating an environment3233The SDK adds `managed-agents-2026-04-01` automatically. TypeScript:3435```ts36const env = await client.beta.environments.create({37name: "my_env",38config: {39type: "cloud",40networking: { type: "unrestricted" },41},42});43```4445### Self-hosted sandboxes4647To run tool execution in **your own infrastructure** instead of Anthropic's, set `config: {type: "self_hosted"}` — the agent loop stays on Anthropic's side, but `bash` / file ops / code execute in a container you control via an outbound-polling worker. The `networking` block does not apply (you control egress). Resource mounting (`file`, `github_repository`) and memory stores behave differently — see `shared/managed-agents-self-hosted-sandboxes.md` for the worker, credentials, and cloud-vs-self-hosted comparison.4849### Environment CRUD5051| Operation | Method | Path | Notes |52| ---------------- | -------- | ------------------------------------------ | ----- |53| Create | `POST` | `/v1/environments` | |54| List | `GET` | `/v1/environments` | Paginated (`limit`, `after_id`, `before_id`) |55| Get | `GET` | `/v1/environments/{id}` | |56| Update | `POST` | `/v1/environments/{id}` | Changes apply only to **new** containers; existing sessions keep their original config |57| Delete | `DELETE` | `/v1/environments/{id}` | Returns 204. |58| Archive | `POST` | `/v1/environments/{id}/archive` | Makes it **read-only**; existing sessions continue, new sessions cannot reference it. No unarchive — terminal state. |5960---6162## Resources6364Attach files, GitHub repositories, and memory stores to a session. **Session creation blocks until all resources are mounted** — the container won't go `running` until every file and repo is in place. Max **999 file resources** per session. Multiple GitHub repositories per session are supported. For `type: "memory_store"` resources (persistent cross-session memory — max 8 per session), see `shared/managed-agents-memory.md`.6566### File Uploads (input — host → agent)6768Upload a file first via the Files API, then reference by `file_id` + `mount_path`:6970```ts71// 1. Upload72const file = await client.beta.files.upload({73file: fs.createReadStream("data.csv"),74});7576// 2. Attach as a session resource77const session = await client.beta.sessions.create({78agent: agent.id,79environment_id: envId,80resources: [81{ type: "file", file_id: file.id, mount_path: "/workspace/data.csv" }82],83});84```8586**`mount_path` is required** and must be absolute. Parent directories are created automatically. Agent working directory defaults to `/workspace`. Files are mounted read-only — the agent writes modified versions to new paths.8788### Session outputs (output — agent → host)8990The agent can write files to `/mnt/session/outputs/` during a session. These are automatically captured by the Files API and can be listed and downloaded afterwards:9192```ts93// After the turn completes, list output files scoped to this session:94for await (const f of client.beta.files.list({95scope_id: session.id,96betas: ["managed-agents-2026-04-01"],97})) {98console.log(f.filename, f.size_bytes);99const resp = await client.beta.files.download(f.id);100const text = await resp.text();101}102```103104**Requirements:**105- The `write` tool (or `bash`) must be enabled for the agent to create output files.106- Session-scoped `files.list` / `files.download` captures outputs written to `/mnt/session/outputs/`.107- The filter parameter is **`scope_id`** (REST query param `?scope_id=<session_id>`). The SDK's files resource auto-adds only the `files-api-2025-04-14` header, so pass `betas: ["managed-agents-2026-04-01"]` explicitly (or both headers on raw HTTP) — without it the API may reject `scope_id` as an unknown field. Requires `@anthropic-ai/sdk` ≥ 0.88.0 / `anthropic` (Python) ≥ 0.92.0 — older versions don't type `scope_id`. The `ant` CLI does **not** expose this flag yet; use the SDK or curl.108- Pass the session ID returned by `sessions.create()` verbatim (e.g. `sesn_011CZx...`) — the API validates the prefix.109- There's a brief indexing lag (~1–3s) between `session.status_idle` and output files appearing in `files.list`. Retry once or twice if empty.110111> **Fallback when `scope_id` filtering is unavailable** (older SDK, or endpoint returns an error): send a follow-up `user.message` asking the agent to `read` each file under `/mnt/session/outputs/` and return the contents. The agent streams the file bodies back as `agent.message` text. This works for text files only and costs output tokens — use it to unblock, not as the primary path.112113This gives you a bidirectional file bridge: upload reference data in, download agent artifacts out.114115### GitHub Repositories116117Clones a GitHub repository into the session container during initialization, before the agent begins execution. The agent can read, edit, commit, and push via `bash` (`git`). Multiple repositories per session are supported — add one `resources` entry per repo. Repositories are cached, so future sessions that use the same repository start faster.118119Repositories are attached for the lifetime of the session — to change which repositories are mounted, create a new session. You **can** rotate a repository's `authorization_token` on a running session via `client.beta.sessions.resources.update(resource_id, {session_id, authorization_token})`; the resource `id` is returned at session creation and by `resources.list()`.120121**Fields:**122123| Field | Required | Notes |124|---|---|---|125| `type` | ✅ | `"github_repository"` |126| `url` | ✅ | The GitHub repository URL |127| `authorization_token` | ✅ | GitHub Personal Access Token with repository access. **Never echoed in API responses.** |128| `mount_path` | ❌ | Path where the repository will be cloned. Defaults to `/workspace/<repo-name>`. |129| `checkout` | ❌ | `{type: "branch", name: "..."}` or `{type: "commit", sha: "..."}`. Defaults to the repo's default branch. |130131**Token permission levels** (fine-grained PATs):132- `Contents: Read` — clone only133- `Contents: Read and write` — push changes and create pull requests134135**How auth works:** `authorization_token` is never placed inside the container. `git pull` / `git push` and GitHub REST calls against the attached repository are routed through an Anthropic-side git proxy that injects the token after the request leaves the sandbox. Code running in the container — including anything the agent writes — cannot read or exfiltrate it.136137> ‼️ **To generate pull requests** you also need GitHub **MCP server** access — the `github_repository` resource gives filesystem + git access only. See `shared/managed-agents-tools.md` → MCP Servers. The PR workflow is: edit files in the mounted repo → push branch via `bash` (authenticated via the git proxy using `authorization_token`) → create PR via the MCP `create_pull_request` tool (authenticated via the vault).138139**TypeScript:**140141```ts142// 1. Create the agent — declare GitHub MCP (no auth here)143const agent = await client.beta.agents.create(144{145name: 'GitHub Agent',146model: 'claude-opus-4-8',147mcp_servers: [148{ type: 'url', name: 'github', url: 'https://api.githubcopilot.com/mcp/' },149],150tools: [151{ type: 'agent_toolset_20260401', default_config: { enabled: true } },152{ type: 'mcp_toolset', mcp_server_name: 'github' },153],154},155);156157// 2. Start a session — attach vault for MCP auth + mount the repo158const session = await client.beta.sessions.create({159agent: agent.id,160environment_id: envId,161vault_ids: [vaultId], // vault contains the GitHub MCP OAuth credential162resources: [163{164type: 'github_repository',165url: 'https://github.com/owner/repo',166authorization_token: process.env.GITHUB_TOKEN, // repo clone token (≠ MCP auth)167checkout: { type: 'branch', name: 'main' },168},169],170});171```172173**Python:**174175```python176import os177178agent = client.beta.agents.create(179name="GitHub Agent",180model="claude-opus-4-8",181mcp_servers=[{182"type": "url",183"name": "github",184"url": "https://api.githubcopilot.com/mcp/",185}],186tools=[187{"type": "agent_toolset_20260401", "default_config": {"enabled": True}},188{"type": "mcp_toolset", "mcp_server_name": "github"},189],190)191192session = client.beta.sessions.create(193agent=agent.id,194environment_id=env_id,195vault_ids=[vault_id], # vault contains the GitHub MCP OAuth credential196resources=[{197"type": "github_repository",198"url": "https://github.com/owner/repo",199"authorization_token": os.environ["GITHUB_TOKEN"], # repo clone token (≠ MCP auth)200"checkout": {"type": "branch", "name": "main"},201}],202)203```204205---206207## Files API208209Upload and manage files for use as session resources, and download files the agent wrote to `/mnt/session/outputs/`.210211| Operation | Method | Path | SDK |212| ---------------- | -------- | ------------------------------------- | --- |213| Upload | `POST` | `/v1/files` | `client.beta.files.upload({ file })` |214| List | `GET` | `/v1/files?scope_id=...` | `client.beta.files.list({ scope_id, betas: ["managed-agents-2026-04-01"] })` |215| Get Metadata | `GET` | `/v1/files/{id}` | `client.beta.files.retrieveMetadata(id)` |216| Download | `GET` | `/v1/files/{id}/content` | `client.beta.files.download(id)` → `Response` |217| Delete | `DELETE` | `/v1/files/{id}` | `client.beta.files.delete(id)` |218219The `scope_id` filter on List scopes the results to files written to `/mnt/session/outputs/` by that session. Without the filter, you get all files uploaded to your account.220