OpenRouter’s shell workflow is useful when a model needs to read a file, run code, inspect an error, and return an artifact. The important limitation is that openrouter:shell, containers, and the Files API are beta, so start with a bounded job rather than a production-critical execution path.
The short answer: when OpenRouter shell is worth using
OpenRouter’s openrouter:shell gives a tool-calling model a hosted Linux environment. The model can issue commands, receive stdout, stderr, and an exit code, then revise its work. The Files API supplies the handoff layer for inputs and outputs.
Choose it when you want:
- A model-agnostic agent that runs code away from your application server.
- A repeatable file-processing job, such as CSV analysis, PDF extraction, or report generation.
- Server-side tool execution without building your own sandbox first.
Do not treat it as a drop-in replacement for a local shell. Networking is disabled by default, containers are not automatically persistent, and the API may change during the beta.
The architecture that matters in practice
| Piece | What it does | The detail that changes your design |
|---|---|---|
openrouter:shell | Lets a tool-capable model run commands | Available through the Responses API and Anthropic Messages API (announcement) |
| Container | Runs commands in an isolated Linux environment | New containers are fresh unless you reuse a session or container reference |
| Files API | Stores inputs and promoted outputs | Direct uploads are attachable but documented as non-downloadable (upload reference) |
openrouter:bash is the Anthropic-compatible alternative. Its default execution path asks the application to run commands locally; set engine: "openrouter" when remote execution is required, as described in the shell announcement.
A file’s trip through the system
1. Upload and attach the input
Upload a file with POST /api/v1/files as multipart form data. The upload reference documents a maximum individual file size of 100 MB and an optional workspace_id query parameter.
curl -X POST https://openrouter.ai/api/v1/files \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-F "file=@data/sales.csv"
The response returns metadata including a file ID, filename, MIME type, byte size, creation time, and a downloadable flag. Attach the returned file ID in the shell environment’s file_ids array.
Attached files are copied into the container as writable copies. A container can receive up to 20 attached files, according to the shell announcement. Editing the copy does not modify the original workspace file.
A developer specifically welcomed Files API support after describing earlier PDF/OCR friction, a small but concrete signal that file handling was a real integration pain point (post).
2. Run, inspect, and iterate
The model sends a batch of commands to the container. Each invocation returns its output and exit status, allowing the model to repair a failed script instead of guessing from the original prompt (shell announcement).
The default network policy is deny-all. If the job needs package downloads or external requests, configure an allowlist when creating the container. OpenRouter documents ports 80 and 443 for allowlisted hosts; the policy cannot be changed after startup. Requests to domains outside the allowlist can fail with HTTP 520 (shell announcement).
Only files under /workspace/home are captured in shell results. Write the artifact there if you expect the API to report it. Files created or changed by the shell receive cfile_ identifiers (shell announcement).
3. Download or promote the output
A shell-produced file can be retrieved through the container file-content endpoint:
GET /api/v1/containers/{container_id}/files/{file_id}/content
The cfile_ identifier belongs to the container. If the artifact needs to survive beyond the container lifecycle, promote it into workspace storage. Promotion creates a new or_file_ identifier that can be attached to a later run (shell announcement).
| File type | Typical ID | Can the Files API download it? | Best use |
|---|---|---|---|
| Direct upload | or_file_... | No, according to the download reference | Input to a later run |
| Container artifact | cfile_... | Through the container endpoint | Temporary output |
| Promoted artifact | or_file_... | Yes | Reusable or longer-lived output |
Container files are retained for 30 days. Promote anything that must be kept longer (shell announcement). The general file-download endpoint returns raw bytes and documents HTTP 400 for user-uploaded files, so a direct upload should be treated as an input, not a general-purpose object-store object.
Cost and limits that change the design
OpenRouter’s shell announcement states that active sandbox time costs $0.0001 per second. A cold container has a 30-second minimum, making the minimum sandbox charge $0.003 by calculation. Token charges are separate.
| Constraint | Documented value | Design implication |
|---|---|---|
| Active sandbox time | $0.0001/second | Long commands add cost continuously |
| Cold-container minimum | 30 seconds | Tiny jobs can trigger the minimum |
| Container sleep | 5 minutes idle | Reuse can still incur a new cold minimum after sleep |
| Files per container | 20 | Bundle inputs or stage them deliberately |
| Individual upload size | 100 MB | Split or preprocess larger files |
| Workspace storage | 10 GiB | Delete or archive old artifacts |
| Unpromoted container retention | 30 days | Promote important outputs |
Reuse a warm container for related steps, avoid unnecessary model-tool loops, and log token cost separately from sandbox cost. The announcement says the Logs view shows model activity and sandbox execution as separate timeline rows.
Core request structure
The exact environment schema can change during beta, but the documented flow is structurally this: upload first, then pass the returned file ID to a shell-enabled request. Keep the request adapter small so you can update it if the beta schema changes.
{
"model": "your/tool-capable-model",
"tools": [
{
"type": "openrouter:shell",
"environment": {
"type": "container_auto",
"file_ids": ["or_file_your_uploaded_file_id"]
}
}
],
"input": "Analyze the attached CSV and write a summary to /workspace/home/report.md"
}
Send this shape to the Responses endpoint documented in the announcement. Before production use, verify the current request schema and response fields against the live server-tools documentation.
Use this sequence for a first integration:
- Upload one small input file and record the returned file ID.
- Create a request for a tool-capable model with
openrouter:shellintools. - Attach the file explicitly through
file_ids. - Ask the model to write outputs below
/workspace/home. - Inspect the exit code and file list before treating the job as successful.
- Download the container artifact or promote it if it must be reused.
- Record token usage and sandbox duration as separate cost fields.
For a multi-request workflow, pass a session_id or explicit container reference. Otherwise, a later request may receive a fresh container with none of the previous state.
What breaks first—and how to design around it
| Failure | Design response |
|---|---|
| The model cannot call the tool | Select a model with tool-calling support; declaring a server tool does not add that capability. |
| The command cannot reach the internet | Start with deny-all networking and configure the allowlist before startup. |
| The output disappears | Write under /workspace/home and use the returned cfile_ ID. Promote durable artifacts. |
| An upload cannot be downloaded | Treat direct uploads as inputs; retrieve shell outputs through the container endpoint or promotion flow. |
| A second request loses the project | Reuse the session or container reference. Fresh containers are the default. |
| The bill is higher than expected | Separate token charges from sandbox time and include the 30-second cold minimum. |
| The interface changes | Keep the beta integration behind an adapter and test identifiers, downloadability, and reuse. |
OpenRouter shell and Files API FAQ
Is OpenRouter shell running commands on my computer?
No. openrouter:shell is designed to execute commands in an OpenRouter-hosted sandbox. The Anthropic-compatible openrouter:bash has different defaults; use engine: "openrouter" for remote execution (shell announcement).
How do I keep files between requests?
Reuse a session or container reference. Without that explicit reuse path, a later request may start with a fresh container.
What is the difference between or_file_ and cfile_?
or_file_ identifies a workspace Files API object. cfile_ identifies a file created or changed inside a container. Promotion converts a container artifact into a new workspace file ID.
Does the Files API charge a separate usage fee?
The shell announcement says Files API usage has no separate usage charge, while workspace storage is limited to 10 GiB. Shell sandbox time and model token usage are still billed according to their applicable rates.
Is the shell tool production-ready?
It is documented as beta, and the announcement warns that the API may change. Use explicit limits, bounded commands, application-level restrictions, and a fallback path before putting it behind an unattended production workflow.
Choose it if your workflow has a real artifact
OpenRouter’s shell and Files API fit a staged pipeline that produces a cleaned CSV, report, transformed image, or compiled artifact. Use explicit file IDs, a predeclared network policy, container reuse, and promotion for durable outputs.
If the task is only a text answer, the extra sandbox cost and lifecycle handling are unnecessary. If it needs local credentials, unrestricted networking, or hard production guarantees, keep execution in infrastructure you control until the beta is mature enough for that risk.
Sources: OpenRouter shell and Files API announcement, Files API upload reference, file content download reference.