Room 42, home

Deploy your first agent

What changes when an agent leaves your laptop: where it runs, how it gets secrets and tools, and the smallest safe first deployment.

Agentsadvanced9 min readUpdated 14 Jun 2026

In short

  1. 01Deploying an agent moves the same loop off your laptop, so three things change: where it runs, how it gets secrets and tools, and how you bound it.
  2. 02Start with a container running the SDK, and inject the key at run time from a secret store, never baked into an image or committed file.
  3. 03Give the agent the smallest allowed tool list the job needs and reach owned systems through MCP, since an unattended run has no human to approve steps.
  4. 04The safest first deployment is a read-only reviewer that writes a report, with a turn limit and logs you actually read.
Contents · 9 sections
  1. 1What changes when an agent leaves your laptop?
  2. 2Where does a deployed agent run?
  3. 3How does a deployed agent get its API key?
  4. 4How does a deployed agent get its tools?
  5. 5How do I limit what an agent can do when nobody is watching?
  6. 6The smallest safe first deployment
  7. 7Watch the run
  8. 8A checklist before you ship
  9. 9Where to go next

Deploying an agent means moving the same agent loop you ran on your laptop into a place that runs without you watching it. Three things change: where the code runs, how it gets its secrets and tools, and how you bound what it is allowed to do when nobody is there to click "approve".

On your machine the agent borrows a lot for free. It uses your shell, your files, your API key sitting in your shell profile, and you, the human, approving each risky step. A server has none of that. The job of a first deployment is to hand the agent each of those things on purpose, and nothing more.

What changes when an agent leaves your laptop?

Your laptop run and your deployed run are the same agent loop. The loop calls the model, the model asks to run a tool, the tool runs, the result goes back, repeat until done. The Claude Agent SDK runs that loop for you in either place. What differs is everything around the loop.

So a deployment is four decisions: pick a host, supply the secret, fix the tool list, and capture the output. Take them one at a time.

Where does a deployed agent run?

You have three broad options. Pick the smallest one that fits.

HostWhat it isGood first fit
A containerYour code in an image you run anywhereYes, most teams start here
A CI jobThe agent runs inside a pipeline stepGood for code tasks on a repo
Managed agentsAnthropic runs the loop and the sandboxWhen you do not want to run infra

A container is the common starting point because it is portable and you control it. You build an image, set environment variables, and run it. The agent works on files and services inside that container, not on your laptop.

The other end of the spectrum is letting Anthropic host the loop for you. With managed agents the loop and a per-session sandbox run on Anthropic infrastructure, and your app sends events and reads back results over a REST API. A common path is to prototype with the SDK locally, then move to managed agents once you do not want to operate sandboxes yourself.

For a first deployment, start with a container running the SDK. Everything below assumes that.

How does a deployed agent get its API key?

On your laptop the agent reads ANTHROPIC_API_KEY from your shell. The SDK does the same thing on a server: it reads the key from an environment variable.

# the SDK reads this from the environment, same as on your laptop
export ANTHROPIC_API_KEY=your-api-key

The change is where that value comes from. HardcodingA secret value typed into a script, config file, or image that anyone with the file can read the key is the most common deployment mistake, and it is a real one. Never put the key in your Dockerfile, your pipeline YAML, or any file you commit. Anyone who can read the file, or the image layers, or the git history, then has your key.

Instead, inject it at run time from whatever your host already provides:

  • In CI, use the pipeline's secret store (for example a repository or organisation secret) and expose it to the step as an environment variable.
  • In a container platform, set it as a secret environment variable on the service, not baked into the image.
  • In a cloud, read it from the platform's secrets manager at start-up.

If you run Claude on a cloud provider instead of the Anthropic API directly, you set a different flag and use that cloud's normal credentials rather than an Anthropic key. For example, Amazon Bedrock uses CLAUDE_CODE_USE_BEDROCK=1 plus your AWS credentials, and Google Vertex AI uses CLAUDE_CODE_USE_VERTEX=1 plus your Google Cloud credentials. The principle is identical: the secret lives in the platform, the agent reads it at run time, nothing is committed.

A practical habit: rotate the key on a schedule, and rotate it immediately if you think it leaked. A deployed agent runs unattended, so a leaked key can be abused for a long time before anyone notices.

How does a deployed agent get its tools?

A tool is anything the agent can do beyond talking: read a file, run a shell command, search the web, call your service. On your laptop you gave it broad access because you were watching. Unattended, you give it the smallest set the job needs.

You declare the allowed built-in tools as a plain list. The names are the same as in Claude Code: Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch. A read-only reviewing agent, for example, gets only the tools that read:

{
  "allowedTools": ["Read", "Glob", "Grep"]
}

That single list is your strongest safety control. An agent that has never been given Bash or Write cannot run a command or change a file, no matter what the model decides it wants to do. Start from nothing and add only what the task proves it needs.

When the agent needs to reach a system you own, a database or your own API, you do not hand it raw credentials. You expose that system as an MCP server and let the agent call it through that. MCP is a uniform interface for tools and data, so the same wiring works locally and in production. You list the servers the agent may connect to as config:

{
  "mcpServers": {
    "store-db": {
      "command": "npx",
      "args": ["-y", "@your-org/store-db-mcp"]
    }
  }
}

In a deployment, treat an MCP server like any other dependency: it needs its own secrets (a database URL, an API token), and those come from the environment too, never from a committed file. If you connect untrusted or third-party MCP servers, read MCP security basics first, because a tool the agent can call is a tool an attacker can try to reach through the agent.

How do I limit what an agent can do when nobody is watching?

On your laptop, a permission prompt is your safety net: the agent pauses and asks before doing something risky. A server has no human to answer that prompt. So an unattended agent must never depend on one.

The SDK ships permission modes that set how cautious the loop is:

  • default · ask before anything risky
  • acceptEdits · auto-approve file edits, still gate the rest
  • plan · explore and propose, change nothing
  • bypassPermissions · skip prompts entirely

For a deployment, the combination that matters is a tight allowedTools allow-list plus a mode that does not hang waiting for input. The default mode is fine when you pair it with a permission callback, a function the SDK calls for anything not already resolved by your allow-list, so it returns a yes or no in code instead of waiting for a person.

Never use bypassPermissions outside an isolated sandboxA locked-down environment where code runs with no access to anything outside it, so a mistake or attack cannot reach the rest of your systems. It removes every guardrail at once, which is exactly what you do not want on a host that touches real systems. If you think you need it, the safer answer is usually a shorter allowedTools list and a sandbox with no network and no access to anything outside the task.

The principle is fail closed. Anything you did not explicitly allow should be denied automatically, not left to a prompt that nobody will answer.

The smallest safe first deployment

Here is a first deployment that is useful and hard to get wrong: a read-only agent that reviews a codebase and writes a report. It cannot edit files, cannot run commands, and cannot reach the network beyond the model. The worst case is a wrong opinion in a text file.

You can prove the exact shape of the run from the CLI before you wrap it in a service. Claude Code runs the same loop in one shot with -p (print mode), and a trailing tool allow-list:

# one-shot, read-only, prints the result and exits
claude -p "Review the auth module for security issues. Write findings to review.md" \
  --allowedTools "Read,Glob,Grep,Write"

Print modeA run that finishes on its own and prints a result, instead of opening an interactive chat session is the bridge between your laptop and a server: it takes a prompt, runs to completion, and exits with output you can capture. That is exactly what a host needs.

Use a tight, explicit prompt so the unattended run has no room to wander:

Try this prompt
You are reviewing a codebase. Do not modify any files except review.md. Steps: 1. Read the files under src/auth. 2. List concrete security risks you can see, with file and line. 3. For each risk, say why it matters and one fix. 4. Write the result to review.md as a short markdown report. Rules: - Do not run shell commands. - If you are unsure about a file, say so rather than guess.

When that one-shot behaves the way you want, you have your deployment: the same prompt, the same allow-list, the same key from the environment, now running on a host on a trigger you choose. Wrap it so the run is reproducible:

# build an image that contains your code, not your secret
docker build -t store-review-agent .
 
# run it, injecting the key at run time from your shell or CI secret
docker run --rm -e ANTHROPIC_API_KEY store-review-agent

Notice the key is passed in at docker run, not built into the image. The image is safe to push to a registry; the secret never leaves the run.Common gotchaThe -e ANTHROPIC_API_KEY form with no =value only forwards the variable if it is set in the calling shell or CI environment; when it is unset, Docker passes nothing and the container starts with an empty key, so the agent fails on its first model call with a confusing 401 rather than a clear "key missing" error.Verify the variable is exported in the run context first, or pass -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" and let the run fail loudly if it is blank.

Watch the run

Unattended does not mean unobserved. The agent loop emits a stream of structured messages: each step it takes, each tool it calls, and a final result that includes the outcome and the cost. Send that stream to your logs.

You read those logs for three things: did it finish, what did it touch, and what did it spend. The final result message carries token usage, which is how you keep an eye on cost before a runaway loop becomes an expensive surprise. A sensible first deployment also has a hard stop: a maximum number of turns or a wall-clock timeout, so a confused agent halts instead of looping forever.Common gotchaSet the turn limit before the first run, not after. On a laptop you notice a stuck loop and hit Ctrl-C; an unattended agent with no cap can spend hours and a large bill calling the model in circles before anyone checks the logs.Give it a low ceiling (say 15 turns) and raise it only once you have seen real runs finish under it.

A checklist before you ship

Run through this before the first unattended run:

  • The key is injected at run time, not in the image, the YAML, or git.
  • allowedTools lists only what the task needs, nothing more.
  • No bypassPermissions outside a sandbox; the run fails closed.
  • Every external system is reached through MCP, with its own injected secrets.
  • There is a turn limit or timeout so the loop cannot run forever.
  • The message stream goes to logs you will read.
  • You tested the exact prompt and allow-list as a one-shot first.

Where to go next

A read-only reviewer is a real deployment and a safe place to learn the moving parts. Once it runs cleanly, you widen it on purpose: add Edit for an agent that proposes patches, add an MCP server for an agent that reads your database, add a permission callback for the few decisions you want to make in code.

If you want stronger guardrails as you widen the blast radius, read hooks and guardrails for code that runs at fixed points in the loop. And if running your own host stops being worth it, that is the signal to look at managed agents, where the infrastructure becomes someone else's problem and you keep the prompt, the tools, and the rules.