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

# File structure

> How to organize an application built with the Autonomy Framework.

Every Autonomy application follows this structure:

```text File Structure: theme={null}
my-app/
|-- autonomy.yaml         # Zone configuration
|-- images/               # Container images
    |-- main/             # Main container image
    |   |-- Dockerfile    # Instructions to build the image
    |   |-- main.py       # Application entry point
    |
    |-- ...               # More images
```

***

## autonomy.yaml

This configuration file defines a [zone](/applications/runtime-architecture#zone)
in your [cluster](/applications/runtime-architecture#cluster) in the
[Autonomy Computer](/what-is-autonomy#autonomy-computer). Think of a zone as
your app's dedicated infrastructure. The Autonomy Computer provisions
everything needed to run it.

```yaml autonomy.yaml theme={null}
name: hello
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main
```

* **`name: hello`** - The zone's name (must be `≤ 10` characters, using only `a to z` or `0 to 9`).
* **`pods`** - List of [pods](/applications/runtime-architecture#pod) to create in this zone (a pod is a group of containers that run together).
* **`public: true`** - Serve the HTTP server on port 8000 of this pod on a public address over HTTPS.
* **`containers`** - List of [containers](/applications/runtime-architecture#container) in the `main-pod`.
* **`image: main`** - Create the `main` container using the image defined in `images/main`.

### Environment variables and secrets

You can set environment variables in your containers:

```yaml autonomy.yaml theme={null}
name: myapp
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main
        env:
          - LOG_LEVEL: "INFO"
          - API_KEY: secrets.API_KEY
```

Create `secrets.yaml` for sensitive values:

```yaml secrets.yaml theme={null}
API_KEY: sk-abc123xyz
```

<Warning>
  Add `secrets.yaml` to `.gitignore` to keep it out of version control.
</Warning>

### Multiple containers

Add multiple containers to a pod for tools agents need:

```yaml autonomy.yaml theme={null}
name: myapp
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main
      
      - name: mcp
        image: ghcr.io/build-trust/mcp-proxy
        env:
          - BRAVE_API_KEY: secrets.BRAVE_API_KEY
        args: ["--sse-port", "8001", "--pass-environment", "--",
               "npx", "-y", "@modelcontextprotocol/server-brave-search"]
```

Containers in the same pod:

* Share the same network namespace.
* Can communicate via `localhost`.

This pattern works for:

* MCP servers (Model Context Protocol tools).
* Python functions, simple binaries, or any TCP service your agents need.
* Creating **private links to enterprise data** sources.

### Multiple pods

Split your application across pods:

```yaml autonomy.yaml theme={null}
name: myapp
pods:
  - name: main-pod
    public: true
    containers:
      - name: main
        image: main

  - name: runner-pod
    clones: 5
    containers:
      - name: runner
        image: runner
```

Use `clones` to run multiple copies of a pod for parallel processing.

***

## Dockerfile

Autonomy provides two base images (both include the Autonomy Framework pre-installed):

* **Development variant** (`ghcr.io/build-trust/autonomy-python-dev`) - Contains `pip`, `uv`, and `apk` package managers plus `bash`, `ash`, and `sh` shells.
* **Minimal variant** (`ghcr.io/build-trust/autonomy-python`) - Removes shells and package managers for additional security and reduced size.

In simple Dockerfiles uses the minimal base image:

```dockerfile images/main/Dockerfile theme={null}
FROM ghcr.io/build-trust/autonomy-python
COPY . .
ENTRYPOINT ["python", "main.py"]
```

### Python dependencies

Use multi-stage builds to install packages using `pip` and `requirements.txt`:

```dockerfile images/main/Dockerfile theme={null}
FROM ghcr.io/build-trust/autonomy-python-dev AS dev
COPY requirements.txt ./
RUN pip install -r requirements.txt

FROM ghcr.io/build-trust/autonomy-python
COPY --from=dev /app/venv venv
COPY . .
ENTRYPOINT ["python", "main.py"]
```

Create `requirements.txt`:

```txt images/main/requirements.txt theme={null}
httpx
markitdown
```

Or use `uv` with `pyproject.toml`:

```dockerfile images/main/Dockerfile theme={null}
FROM ghcr.io/build-trust/autonomy-python-dev AS dev
COPY pyproject.toml ./
RUN uv pip install -r pyproject.toml

FROM ghcr.io/build-trust/autonomy-python
COPY --from=dev /app/venv venv
COPY . .
ENTRYPOINT ["python", "main.py"]
```

Create `pyproject.toml`:

```toml images/main/pyproject.toml theme={null}
[project]
name = "my-app"
version = "0.1.0"
dependencies = [
    "httpx",
    "markitdown",
]
```

### System dependencies

For system packages like `ffmpeg`, use the development image as your base:

```dockerfile images/main/Dockerfile theme={null}
FROM ghcr.io/build-trust/autonomy-python-dev

# Install system packages with apk (as root)
USER root
RUN apk add --no-cache ffmpeg
USER nonroot

# Install Python packages
COPY requirements.txt ./
RUN pip install -r requirements.txt

COPY . .
ENTRYPOINT ["python", "main.py"]
```

<Note>
  When you need system shared libraries, use `ghcr.io/build-trust/autonomy-python-dev` as your base image.
</Note>

***

## main.py

The entrypoint to your application:

### One module

For a simple application with a single file:

```python images/main/main.py theme={null}
from autonomy import Agent, Model, Node

async def main(node):
  await Agent.start(
    node=node,
    name="henry",
    instructions="You are Henry, an expert legal assistant",
    model=Model("claude-sonnet-4-v1")
  )

Node.start(main)
```

This Python module:

1. **Imports modules from the [Autonomy Framework](/what-is-autonomy#autonomy-framework)**
   which provides `Agent`, `Model`, and `Node`.
2. **Defines an async main function** that:
   * Starts an agent named "henry".
   * Gives it instructions to act as a legal assistant.
   * Configures it to use Claude Sonnet 4 model.
3. **Starts an Autonomy Node** - This creates the actor runtime that hosts your agent and
   invokes the main function. It also starts an HTTP server on port `8000` with a set of
   [built-in APIs](/applications/programming-interfaces#built-in-apis) to interact with your agent.

### Multiple modules

For larger applications, organize code into multiple modules:

```
images/main/
|-- Dockerfile
|-- main.py
|-- accounts/
    |-- __init__.py
    |-- balance_inquiry.py
    |-- statements.py
|-- transactions/
    |-- __init__.py
    |-- history.py
    |-- categorization.py
|-- budgeting/
    |-- __init__.py
    |-- analysis.py
    |-- recommendations.py
|-- investments/
    |-- __init__.py
    |-- portfolio.py
    |-- performance.py
```

Entry point:

```python images/main/main.py theme={null}
from autonomy import Agent, Model, Node
from accounts.balance_inquiry import get_balance
from transactions.history import get_transactions

async def main(node):
  await Agent.start(
    node=node,
    name="finn",
    instructions="You are Finn, a personal financial assistant",
    model=Model("claude-sonnet-4-v1"),
    tools=[get_balance, get_transactions]
  )

Node.start(main)
```

This structure helps you:

* Separate concerns.
* Reuse code.
* Test components independently.
* Keep you code easy to manage as your application grows.
