---
title: Run Agent Barn locally
canonical: "https://agentbarn.dev/guides/get-started/local-quickstart"
pubDate: "2026-08-29T00:00:00.000Z"
updatedDate: "2026-09-09T09:19:24.000Z"
author: Agent Barn
description: "Start the local Docker and k3d stack, configure model access, and create an Agent without a GitHub token for runtime builds."
tags: [Get started, Quickstart, Evaluators and contributors, local quickstart, Docker, k3d, OpenRouter, runtime images, cost-sync]
categories: [Guides, Get started]
---

Start the complete Agent Barn development environment with Docker. When you finish, you will have the web app, Product API, Ingest API, Communications service, Domain Event worker, LiteLLM and its PostgreSQL database, the application PostgreSQL and Redis services, a local k3d Kubernetes cluster, the Hermes and OpenClaw Runtime images, and Runtime Kubernetes resources for any Agent you start.

Application services run in Docker Compose. Agent Runtime resources run inside the local k3d cluster. The Communications service is required for Communication Connections and provider delivery, and Product, Ingest, and Communications are separate HTTP boundaries rather than one API.

## What you will accomplish

By the end of this guide, you will be able to:

-   Open Agent Barn at `http://localhost:3000`
-   Sign in as the bootstrap Platform Administrator
-   Create an Organization
-   Hire and start a headless Agent inside the local Kubernetes cluster
-   Add a Communication Connection through the local Communications service
-   Route model requests through the local LiteLLM proxy
-   See Conversation Messages and Tool Calls arrive through their separate paths
-   Stop and resume the environment without losing local database data

**First startup**

Agent Barn builds and imports the Hermes and OpenClaw Runtime images. Later startups skip images that are already available in the cluster.

## Before you begin

### Required software

You need only:

-   Git
-   Docker with Linux containers
-   A running Docker daemon
-   Sufficient local CPU, memory, and disk capacity
-   OpenSSL, used below to generate local keys

Run the commands in this guide from a Bash-compatible terminal. On Windows, use WSL2 with Docker Desktop integration enabled. If the `openssl` command is unavailable, install OpenSSL using your operating system's package manager before continuing.

Docker Desktop is the simplest option on macOS and Windows. On Windows, run the repository through WSL2 with Docker Desktop's Linux-container backend.

The complete Docker workflow does not require host installations of Python, Node.js, `uv`, `pnpm`, `k3d`, or Helm. The repository supplies a `k3d-runner` container for the k3d command. Native tools are needed only for host-managed development, testing, or selected maintenance workflows.

**Information**

`kubectl` is optional. Install it only if you want to inspect the local cluster directly; nothing in this guide's startup or verification path requires it.

### Required accounts and credentials

You need:

-   An [OpenRouter API key](https://openrouter.ai/settings/keys) for the models your Agents will use.

Both [Agent Barn](https://github.com/aai-labs/agent-barn) and [aai-cli](https://github.com/aai-labs/aai-cli) are public. You do not need membership in AAI Labs or permission to access a private repository.

You need an OpenRouter API key for the configured model-routing path. The runtime Dockerfiles clone the public `aai-labs/aai-cli` repository directly; the local build does not require a GitHub personal access token. An optional Agent GitHub tool Integration can separately use credentials.

**Keep credentials private**

Use development credentials for the local environment. Never commit `.env` or include secrets in screenshots, logs, prompts, chat messages, or documentation.

### Local ports

Make sure these default host ports are available before starting the stack:

| Port | Service |
| --- | --- |
| `3000` | Agent Barn web app |
| `5432` | Application PostgreSQL database |
| `6379` | Redis |
| `7070` | LiteLLM |
| `8000` | Product API |
| `8001` | Ingest API |
| `8002` | Communications service |
| `16443` | Local k3d Kubernetes API |

These are local development ports. They are not instructions to expose these services to the internet.

If a port is already in use, check the corresponding settings in `.env.spec` and the local cluster configuration before starting. Keep any changed port consistent with the addresses used later in this guide.

## Clone the repository

```
git clone https://github.com/aai-labs/agent-barn.git
cd agent-barn
```

The GitHub repository uses the current `agent-barn` name. The local Kubernetes namespaces intentionally retain the historical `agent-farm` naming.

## Create the local configuration

`./run.sh` expects a `.env` file in the repository root. You do not have to create it by hand:

```
./run.sh
```

If `.env` is missing, `./run.sh` creates it from `.env.spec`, reports the values you still need to supply, and exits. Replace the empty or placeholder values, then run `./run.sh` again.

`.env.spec` remains the authoritative inventory and description of every supported local variable. Read it when you need to know what a setting does.

### Required values

The stack does not start until these values are set:

| Variable | Purpose |
| --- | --- |
| `POSTGRES_USER` | Application database user |
| `POSTGRES_PASSWORD` | Application database password |
| `POSTGRES_DB` | Application database name |
| `POSTGRES_PORT` | Published database port |
| `SECRET_SIGNING_KEY` | Signs application tokens |
| `PLATFORM_ADMIN_CREDENTIALS` | Bootstrap Platform Administrator sign-in |
| `ENVIRONMENT` | Environment name for the local run |
| `UI_APP_URL` | Public URL of the web app |
| `API_PORT` | Published Product API port |
| `AGENT_TOKEN_ENCRYPTION_KEY` | Encrypts stored credentials |
| `OPENROUTER_API_KEY` | Upstream model access for LiteLLM |
| `LITELLM_MASTER_KEY` | Protects LiteLLM virtual keys |
| `OPENCLAW_IMAGE` | Pinned OpenClaw Runtime image reference |
| `HERMES_IMAGE` | Pinned Hermes Runtime image reference |

### Database and application

```
POSTGRES_USER=agentbarn
POSTGRES_PASSWORD=<local-database-password>
POSTGRES_DB=agentbarn
POSTGRES_PORT=5432

API_PORT=8000
ENVIRONMENT=local
UI_APP_URL=http://localhost:3000

SECRET_SIGNING_KEY=<random-signing-key>
PLATFORM_ADMIN_CREDENTIALS=admin@example.com:<secure-password>
```

The Platform Administrator password must contain:

-   At least eight characters
-   An uppercase letter
-   A lowercase letter
-   A digit

Generate a random signing key with:

```
openssl rand -hex 32
```

Do not use the generated signing key as the Platform Administrator password.

### Credential encryption

Agent Barn uses an encryption key to protect stored credentials.

From your terminal, generate a new key:

```
openssl rand -base64 32 | tr '+/' '-_'
```

Copy the generated value into the `AGENT_TOKEN_ENCRYPTION_KEY` entry in the `.env` file at the repository root:

```
AGENT_TOKEN_ENCRYPTION_KEY=PASTE_THE_GENERATED_VALUE_HERE
```

Replace `PASTE_THE_GENERATED_VALUE_HERE` with the complete output from the command. Do not enter the command itself as the value.

Generate this key once for your local installation and keep it stable across restarts. Replacing it later prevents Agent Barn from reading credentials encrypted with the previous key.

Keep `.env` private and do not commit it to Git.

### Model routing

```
OPENROUTER_API_KEY=<openrouter-api-key>
LITELLM_MASTER_KEY=<stable-litellm-master-key>
```

Generate a local LiteLLM master key with:

```
printf 'sk-%s\n' "$(openssl rand -hex 16)"
```

Set the generated value once and keep it stable. LiteLLM uses it to protect the virtual keys it stores. Changing it between runs breaks Agents created with keys protected by the previous value.

### Agent Runtime images

Read the versions pinned by the repository:

```
printf 'OpenClaw: '
cat openclaw-base/VERSION

printf 'Hermes: '
cat hermes-base/VERSION
```

Set both image references using those exact tags:

```
OPENCLAW_IMAGE=agentbarn-openclaw-base:<openclaw-version>
HERMES_IMAGE=agentbarn-hermes-base:<hermes-version>
```

The image tag must match the corresponding `VERSION` file. Startup stops with a clear error when the values do not match.

### Optional ports

These settings have working defaults and only need changing when a port is already in use:

| Variable | Default |
| --- | --- |
| `INGEST_PORT` | `8001` |
| `COMMUNICATIONS_PORT` | `8002` |
| `UI_PORT` | `3000` |
| `LITELLM_PORT` | `7070` |

You do not need to set `API_K8S_KUBECONFIG_PATH`. `./run.sh` writes the expected in-container kubeconfig path automatically.

**Secret handling**

Do not place `OPENROUTER_API_KEY`, `LITELLM_MASTER_KEY`, or `AGENT_TOKEN_ENCRYPTION_KEY` in Dockerfiles, command arguments, committed files, screenshots, or chat messages.

## Start Agent Barn

Start the complete environment:

```
./run.sh
```

To start without following logs:

```
./run.sh --detach
```

The launcher:

1.  Confirms Docker exists and the daemon is running.
2.  Loads `.env` and validates required values.
3.  Starts the local k3d cluster and LiteLLM.
4.  Loads the Hermes and OpenClaw base images into k3d, skipping images already present.
5.  Configures the API container to use the generated internal kubeconfig.
6.  Starts PostgreSQL and Redis.
7.  Builds the API image.
8.  Runs Alembic migrations.
9.  Builds and starts the API, worker, Communications, and UI services.
10.  Follows Compose logs unless detached mode was selected.

**Following logs**

Pressing `Ctrl-C` while logs are being followed detaches from the logs. It does not stop the running stack.

**Initial image build**

Do not interrupt the first Runtime-image build unless it has clearly failed. Later runs skip images that are already loaded.

## Verify the environment

### Check the containers

```
docker compose -f compose.yml ps
```

Expected long-running application services:

-   `db`
-   `redis`
-   `api`
-   `worker`
-   `communications`
-   `ui`
-   LiteLLM services started through the k3d profile

**Important**

The stack is not complete while the `communications` container is absent. Without it, Communication Connections and provider delivery cannot work, even though the Product API responds normally.

### Check the Product API

```
curl --fail http://localhost:8000/api/v1/health
```

This confirms that the Product API can reach PostgreSQL. It does not prove that Ingest, Communications, LiteLLM, or any Agent Runtime is healthy.

### Check the Ingest API

```
curl --fail http://localhost:8001/ingest/v1/openapi.json
```

### Check the Communications service

```
curl --fail http://localhost:8002/health
```

### Optional cluster inspection

If you have `kubectl` installed, you can inspect the local cluster with the generated host kubeconfig:

```
kubectl \
  --kubeconfig .k3d/kubeconfig-host.yaml \
  get namespace agent-farm
```

## Sign in

Open:

[`http://localhost:3000`](http://localhost:3000)

Sign in with the email and password from `PLATFORM_ADMIN_CREDENTIALS` in `.env`. From there:

1.  Create or select an Organization.
2.  Create a headless Agent.
3.  Start the Agent.
4.  Add a Communication Connection separately, when provider messaging is required.

**Information**

A fresh installation does not contain a default Organization. Create an Organization before hiring an Agent, because Agents, Templates, Skills, credentials, activity, and costs are Organization-scoped.

Continue with [Create your first Organization](/guides/get-started/create-organization), then [Hire your first Agent](/guides/get-started/hire-first-agent).

## Your first local Agent

Hiring creates a headless Agent. Communication is a separate, later step.

1.  Create an Organization.
2.  Review the Organization model allowlist and default.
3.  Hire a headless Agent.
4.  Choose Hermes or OpenClaw.
5.  Select a Template.
6.  Configure required Skills and tool Integration credentials.
7.  Start the Agent.
8.  Add one or more Communication Connections.
9.  Complete provider-side setup.
10.  Verify Runtime health and Connection health separately.
11.  Send one allowed provider message.
12.  Inspect the Connection-scoped Conversation.
13.  Use a controlled tool request before expecting a Tool Call.

Hiring does not create Slack, Microsoft Teams, Telegram, or Discord configuration. See [Connect a Platform](/guides/get-started/connect-a-platform) for the Connection workflow and [Verify your Agent](/guides/get-started/verify-agent) for the layered checks.

## What is running

| Service | Local address | Responsibility |
| --- | --- | --- |
| Web app | `http://localhost:3000` | User interface |
| Product API | `http://localhost:8000/api/v1` | Product and administration operations |
| Ingest API | `http://localhost:8001/ingest/v1` | Runtime Tool Call telemetry |
| Communications | `http://localhost:8002/communications/v1` | Runtime communication protocol and provider delivery |
| LiteLLM | `http://localhost:7070` | Model routing and Agent key usage |
| PostgreSQL | `localhost:5432` by default | Agent Barn application database |

A few details matter when you are reading logs or debugging a port:

-   Product and Ingest run as separate processes in the `api` container.
-   Communications runs in its own `communications` container.
-   Containers reach Redis through the Compose network. Redis is also published on host port `6379` by default for local development.
-   LiteLLM uses its own PostgreSQL database, separate from the application database.
-   Host ports can differ when the corresponding `.env` values are changed.

**Information**

Agent Runtime resources run inside k3d. The remaining application services run through Docker Compose.

### The Communications service

Communications runs from the API image as a separate FastAPI application. It listens on port `8002` by default, and its API is mounted beneath `/communications/v1`. It:

-   Supervises supported provider sessions
-   Processes durable inbound and outbound Communication Deliveries
-   Exposes the Runtime-neutral Communications protocol
-   Persists canonical Conversation Messages
-   Maintains Connection health and operational metrics

Agent Runtime pods inside k3d reach it through `host.docker.internal`. The default local base URL is equivalent to:

```
http://host.docker.internal:8002/communications/v1
```

`COMMUNICATIONS_BASE_URL` is configured for Agent Runtime resources and is distinct from the Product API URL.

### Who writes Conversations and Tool Calls

The two Activity paths have different writers:

-   Ingest stores authenticated Runtime Tool Call telemetry.
-   The Communications Gateway writes canonical inbound and outbound Conversation Messages.
-   Product API routes provide authorized reads for both.
-   Conversation identity includes a Communication Connection.

That separation shapes how local failures look:

-   A broken Ingest path can leave Tool Calls empty while provider Conversations continue to work.
-   A broken Communications path can prevent provider messaging while Tool Call ingest and the Product API remain healthy.

See [Activity, conversations, and runtime telemetry](/guides/activity-conversations-and-telemetry).

### How local services reach each other

Application services run in Docker Compose while Agent workloads run in k3d, so Agent Runtime resources reach the application through host-published ports.

#### Browser to Product API

The browser reaches the web app, and the web app reaches the Product API through the existing local application configuration.

#### Agent Runtime to Ingest

```
http://host.docker.internal:8001/ingest/v1
```

#### Agent Runtime to Communications

```
http://host.docker.internal:8002/communications/v1
```

#### Agent Runtime to LiteLLM

```
http://host.docker.internal:7070
```

These host hops are required because of the split between Compose and k3d. Do not substitute Compose-only DNS names in Agent Runtime configuration; a Compose service name is not resolvable from inside a k3d pod.

For how these resources are assembled, see [Runtime assembly and deployment](/guides/runtime-and-deployment).

## Stop or resume the environment

Stop the environment:

```
./stop.sh
```

or:

```
make stop
```

The normal stop:

-   Stops application containers
-   Stops the local k3d cluster
-   Stops LiteLLM services
-   Preserves PostgreSQL and Redis volumes
-   Preserves the k3d cluster for a faster restart

Resume with:

```
./run.sh --detach
```

To stop and reset the local cluster:

```
./stop.sh --clean
```

or:

```
make stop-clean
```

The clean option:

-   Removes the application containers
-   Deletes the k3d cluster
-   Removes generated `.k3d` files
-   Preserves named database and Redis volumes
-   Requires Agent Runtime images to be loaded again at the next startup

**Clean stop**

The clean option does not delete your named database or Redis volumes. Local Organizations, Agents, and history survive it; the next startup recreates the cluster and reloads the Runtime images.

## Success checklist

The local environment is ready when you can confirm:

-   Docker is running
-   `.env` contains all required values
-   PostgreSQL and Redis are healthy
-   Migrations completed
-   The Product API is reachable on `8000`
-   Ingest is reachable on `8001`
-   Communications is reachable on `8002`
-   The UI is reachable on `3000`
-   LiteLLM is reachable through the configured local port
-   The k3d cluster is running
-   The Hermes and OpenClaw images were loaded
-   Platform Administrator sign-in works
-   An Organization can be created or selected
-   A headless Agent can be hired and started
-   A Communication Connection can be added separately
-   Conversation and Tool Call paths are understood as separate

## Troubleshooting

### `./run.sh` reports missing values

Open `.env` and replace the empty or placeholder values named by the script. Use `.env.spec` for descriptions, then run `./run.sh` again.

Do not remove a variable from the validation list to bypass the error.

### Docker is unavailable

Start Docker and confirm Linux containers are enabled. Retry after this succeeds:

```
docker info
```

### Migration fails

Application services do not complete startup when migrations fail. Review the retained migration output and correct the database or migration issue before rerunning.

Do not repeatedly restart the stack without understanding the schema state.

### Startup fails while creating the Platform Administrator

Check `PLATFORM_ADMIN_CREDENTIALS`. Its password must contain at least eight characters, an uppercase letter, a lowercase letter, and a digit.

The high-level error can appear as:

```
500: Error while initializing startup data
```

The API log immediately before that message contains the underlying validation error.

### The Product API works but Tool Calls remain empty

Check Ingest on port `8001`, then confirm that Agent Runtime resources use the correct Ingest base URL:

```
http://host.docker.internal:8001/ingest/v1
```

Also confirm the request actually invoked a tool. A request that uses no tool is not expected to produce a Tool Call.

Do not diagnose this as a Conversation persistence failure.

### The Product API works but provider Conversations remain empty

Check Communications on port `8002`, then confirm:

-   The Agent has an enabled Communication Connection
-   Provider credentials and provider-side setup are complete
-   The Connection's access and mention policy allow the message
-   The Agent Runtime is running

Do not check Ingest as the canonical Conversation writer. See [Communication Connections](/guides/agents/communication-connections).

### A Conversation appears but no reply arrives

Review Agent Runtime health, then review Connection health and delivery diagnostics separately. Confirm outbound provider permissions and that the source Connection remains enabled.

### An Agent cannot start in k3d

Confirm that:

-   The Runtime images were loaded
-   The API container can reach the generated kubeconfig
-   k3d is running

Then review model, Template, Skill, and Integration requirements, along with the Agent lifecycle logs.

### Communications cannot be reached from an Agent pod

Confirm that:

-   The `communications` container is running
-   Host port `8002` is published
-   `COMMUNICATIONS_BASE_URL` uses `host.docker.internal`
-   A local firewall or Docker networking rule is not blocking the host-published port

On native Linux, also verify that the host firewall permits traffic from the k3d bridge network.

### Runtime image tags do not match

`OPENCLAW_IMAGE` and `HERMES_IMAGE` must end with the versions stored in:

```
openclaw-base/VERSION
hermes-base/VERSION
```

Update `.env` so each tag matches its file exactly.

### The Runtime-image build cannot read `aai-cli`

The runtime Dockerfiles clone the public repository directly. Check network access to GitHub and the public source URL; a GitHub token is not a local runtime-build prerequisite.

### An Agent is stuck in `ImagePullBackOff`

Confirm that the image reference in `.env` matches the imported image and the repository `VERSION` file.

Reload missing images with:

```
bash docker/k3d/k3d-load-images.sh
```

### Agent pods are killed with exit code 137

Exit code 137 or `OOMKilled` normally means the Docker environment ran out of memory.

Inspect current usage:

```
docker stats --no-stream
```

Increase the Docker memory allocation or stop unrelated workloads before retrying.

## Next steps

[**Create your first Organization**Read guide](/guides/get-started/create-organization) [**Hire your first headless Agent**Read guide](/guides/get-started/hire-first-agent) [**Connect a Platform to the Agent**Read guide](/guides/get-started/connect-a-platform) [**Verify the Agent layer by layer**Read guide](/guides/get-started/verify-agent) [**Understand Communication Connections**Read guide](/guides/agents/communication-connections) [**Learn how local Agent workloads are assembled**Read guide](/guides/runtime-and-deployment) [**Review the full configuration reference**Read guide](/guides/self-hosting/configuration) [**Troubleshoot a self-hosted deployment**Read guide](/guides/self-hosting/troubleshooting) [**Use the native development workflow for faster API or UI iteration**Read guide](/guides/local-development-and-operations)

Microsoft Teams requires a webhook that Microsoft can reach over public HTTPS. A localhost-only installation does not meet that prerequisite. Before following the [Microsoft Teams guide](/guides/platforms/microsoft-teams), arrange a public endpoint with your installation administrator or prepare a self-hosted deployment.

## Cost freshness and synchronization

See [Cost synchronization](/guides/self-hosting/configure-production#cost-synchronization) for the entrypoint, credentials, schedule, backfill, and healing behavior.

Calls can occur while Costs remains empty or stale. Check cost-sync scheduling and logs, database access, LiteLLM master-key lookup, and upstream availability. An absent record or unresolved OpenRouter lookup does not prove a call was free. Review attribution and recovery backlog separately from Runtime health.

Docker Compose and `run.sh` do not schedule cost synchronization automatically. Local reporting needs an explicit invocation in a configured application environment; refreshing Costs does not perform synchronization.
