# Deploy AI Agents to Kubernetes

This guide shows you how to containerize a Python AI agent and deploy it to Kubernetes, connected to the [Catalyst Cloud](https://docs.diagrid.io/operate/hosting/catalyst-cloud) workflow engine and authorization service.

Your agent code runs in a Kubernetes pod. There is no sidecar to install — the pod connects directly to Catalyst Cloud using three environment variables that you store as a Kubernetes Secret.

```mermaid
---
title: Agent Pod connected to Catalyst Cloud
---
flowchart LR
  subgraph Kubernetes
    POD(Agent Pod)
    SECRET[(catalyst-credentials\nSecret)]
  end
  subgraph Catalyst Cloud
    APPID(ID)
    ENGINE(Workflow Engine\n/ Access Policies)
  end

  SECRET-->POD
  POD-->APPID
  APPID-->ENGINE
```

## Prerequisites

- [Diagrid Catalyst account](https://catalyst.diagrid.io/)
- [Diagrid CLI](https://docs.diagrid.io/references/catalyst/catalyst-cli-intro)
- [Docker](https://docs.docker.com/get-docker/)
- A container registry (Docker Hub, ECR, GCR, ACR, etc.)
- A Kubernetes cluster with `kubectl` configured

## 1. Create a Catalyst project and agent

If you don't already have a project and agent from a previous tutorial:

```bash
diagrid project create my-project
diagrid app create my-agent --project my-project
```

:::tip
Use descriptive names that match your application. You can reuse a project you already created in a previous tutorial — just create a new agent for the Kubernetes deployment.
:::

## 2. Retrieve Catalyst credentials

You need three values to connect your pod to Catalyst: the project's HTTP endpoint, the project's gRPC endpoint, and the agent's API token.

**Get the project endpoints:**

```bash
diagrid project get my-project -o json
```

Look for `status.endpoints.http.url` and `status.endpoints.grpc.url` in the output:

```json
{
  "status": {
    "endpoints": {
      "http": { "url": "https://http-prj123456.cloud.r1.diagrid.io:443" },
      "grpc": { "url": "https://grpc-prj123456.cloud.r1.diagrid.io:443" }
    }
  }
}
```

**Get the agent API token:**

```bash
diagrid app get my-agent --project my-project -o yaml
```

Look for `status.apiToken` in the output:

```yaml
status:
  apiToken: diagrid://v1/...
```

Save all three values — you'll store them as a Kubernetes Secret in a later step.

## 3. Write a Dockerfile

Create a `Dockerfile` in your project directory. The install command differs per framework:

```dockerfile
FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "agent.py"]
```

Create a `requirements.txt` with your framework's dependencies:

**LangGraph**

```text
diagrid[langgraph]
fastapi
uvicorn
```

**CrewAI**

```text
diagrid[crewai]
fastapi
uvicorn
```

**OpenAI Agents**

```text
diagrid[openai_agents]
fastapi
uvicorn
```

**Pydantic AI**

```text
diagrid[pydantic_ai]
fastapi
uvicorn
```

**Google ADK**

```text
diagrid[adk]
fastapi
uvicorn
```

**Strands**

```text
diagrid[strands]
fastapi
uvicorn
```

:::tip
If your agent does not use the `diagrid` SDK (e.g. a plain access policy service invocation app), just list your direct dependencies: `fastapi`, `uvicorn`, `httpx`, etc.
:::

## 4. Build and push the image

Replace `your-registry` and `my-agent` with your registry path and image name.

```bash
docker build -t your-registry/my-agent:latest .
docker push your-registry/my-agent:latest
```

## 5. Store credentials as a Kubernetes Secret

Create a Kubernetes Secret with the three Catalyst credentials you retrieved in step 2:

```bash
kubectl create secret generic catalyst-credentials \
  --from-literal=http-endpoint="https://http-prj123456.cloud.r1.diagrid.io:443" \
  --from-literal=grpc-endpoint="https://grpc-prj123456.cloud.r1.diagrid.io:443" \
  --from-literal=api-token="diagrid://v1/..."
```

:::tip
Replace the placeholder values with the real ones from `diagrid project get` and `diagrid app get`.
:::

## 6. Create a Kubernetes Deployment

Create `deployment.yaml`:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-agent
  template:
    metadata:
      labels:
        app: my-agent
    spec:
      containers:
        - name: my-agent
          image: your-registry/my-agent:latest
          ports:
            - containerPort: 8001
          env:
            - name: DAPR_HTTP_ENDPOINT
              valueFrom:
                secretKeyRef:
                  name: catalyst-credentials
                  key: http-endpoint
            - name: DAPR_GRPC_ENDPOINT
              valueFrom:
                secretKeyRef:
                  name: catalyst-credentials
                  key: grpc-endpoint
            - name: DAPR_API_TOKEN
              valueFrom:
                secretKeyRef:
                  name: catalyst-credentials
                  key: api-token
```

If your agent needs an LLM API key, add it to the secret and reference it the same way:

```yaml
            - name: OPENAI_API_KEY
              valueFrom:
                secretKeyRef:
                  name: catalyst-credentials
                  key: openai-api-key
```

## 7. Apply and verify

Deploy to your cluster:

```bash
kubectl apply -f deployment.yaml
```

Check that the pod is running:

```bash
kubectl get pods
```

Stream the logs to verify the agent connected to Catalyst:

```bash
kubectl logs -f deployment/my-agent
```

You should see the agent start up and, if it uses durable workflows, a message indicating the Dapr workflow runner has connected to Catalyst. If using service invocation, you can `kubectl exec` into the pod or expose it via a Service to send test requests.

## Summary

In this guide, you:

- Created a Catalyst project and agent for Kubernetes use
- Retrieved the HTTP endpoint, gRPC endpoint, and API token
- Containerized your Python agent with a framework-appropriate `requirements.txt`
- Stored Catalyst credentials as a Kubernetes Secret
- Deployed the agent with the three environment variables your code reads from

## Next steps

- Add a [Kubernetes Service](https://kubernetes.io/docs/concepts/services-networking/service/) to expose your agent's HTTP port
- Use [Horizontal Pod Autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) to scale agent replicas
- Learn more about [Catalyst Enterprise](https://docs.diagrid.io/operate/hosting/enterprise-self-hosted) for self-hosted deployments that keep traffic within your private network
