> ## Documentation Index
> Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Shell-only capability for older models

> Run an OpenAI Agents SDK agent with only the shell capability — targets gpt-4.1 and older models that reject grammar-typed custom tools.

## Use case

The full default capability set includes `apply_patch`, a grammar-typed
"custom" tool that gpt-5 and newer models accept but gpt-4.1 rejects
with `Invalid value: 'custom'`. This example drops the filesystem
capability and keeps only `Shell()`. The agent can still read and write
files -- it does so via bash commands (`cat`, `tee`, `sed`, etc.)
instead of the native `apply_patch` / `view_image` tools.

## What you'll learn

* Restricting an agent to `capabilities=[Shell()]` so it works with
  gpt-4.1 and older models
* Configuring PII redaction + prompt-injection scanning via
  `SecurityPolicy`
* Limiting egress to a network allowlist

## Prerequisites

<Snippet file="snippets/env-setup.mdx" />

Also:

```bash theme={null}
export OPENAI_API_KEY="sk-..."
pip install "declaw[openai-agents]"
```

## Code walkthrough

Set up the sandbox client with a security policy and network allowlist:

```python theme={null}
from agents import Runner, set_tracing_disabled
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig
from agents.sandbox.capabilities import Shell

from declaw.openai import (
    DeclawSandboxClient,
    DeclawSandboxClientOptions,
    InjectionDefenseConfig,
    PIIConfig,
    SandboxNetworkOpts,
    SecurityPolicy,
)

set_tracing_disabled(True)

options = DeclawSandboxClientOptions(
    template="python",
    timeout=300,
    security=SecurityPolicy(
        pii=PIIConfig(enabled=True, action="redact"),
        injection_defense=InjectionDefenseConfig(
            enabled=True, sensitivity="medium", domains=["api.openai.com"]
        ),
    ),
    network=SandboxNetworkOpts(
        allow_out=["api.openai.com", "pypi.org", "files.pythonhosted.org"],
    ),
)
```

Create the agent with **only** the shell capability. The key
difference from the standard quickstart is `capabilities=[Shell()]`
and `model="gpt-4.1"`:

```python theme={null}
agent = SandboxAgent(
    name="quickstart-shell-only",
    model="gpt-4.1",
    instructions=(
        "You are a helpful coding agent. You only have a shell "
        "tool — use bash commands (cat, tee, sed, cp, mv, etc.) "
        "for all file work."
    ),
    capabilities=[Shell()],
)
```

Run the agent inside a declaw sandbox:

```python theme={null}
client = DeclawSandboxClient()
session = await client.create(options=options)
try:
    result = await Runner.run(
        agent,
        "Create /workspace/notes.md with 'hello from declaw', then "
        "run `wc -c /workspace/notes.md` and report the byte count.",
        run_config=RunConfig(sandbox=SandboxRunConfig(session=session)),
    )
    print(result.final_output)
finally:
    await client.delete(session)
```

## Expected output

```
I've written the file and measured it:
- /workspace/notes.md -- 18 bytes
```

(Content will vary slightly depending on model output.)

## When to use this

| Scenario              | Capability set                            |
| --------------------- | ----------------------------------------- |
| gpt-5 family or newer | Default (shell + filesystem + compaction) |
| gpt-4.1 or older      | `[Shell()]` only -- this example          |

The security policy (`PIIConfig`, `InjectionDefenseConfig`,
`SandboxNetworkOpts`) works identically regardless of which capability
set the agent uses -- it is enforced at the sandbox's network boundary.

## Full source

See `cookbook/examples/openai-agents-quickstart-shell-only/main.py` in the repo.
