Skip to main content

Deploy Guide

This guide explains how to build a custom agent as a Docker container and register it on the AGENTIC STAR platform for execution.

Overview

The deployment flow consists of 4 steps:

  1. Create Dockerfile — Containerize the agent
  2. Docker Build & Push — Register to a container registry
  3. Platform Registration — Register the agent in the admin console
  4. Verification — Test via the Chat Web App

Prerequisites

  • Docker 24.0 or higher
  • Access to Azure Container Registry (ACR) or a compatible registry (permission to push images; the AcrPush role on Azure)
  • Access permissions to the AGENTIC STAR admin console

Step 1: Create the Dockerfile

DockerfileDockerfile
FROM python:3.12-slim

WORKDIR /app

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

# Copy application code
COPY . .

# Non-root user (a NUMERIC UID is required under runAsNonRoot-enforced namespaces;
# a name-only USER cannot be verified as non-root by the kubelet and is rejected)
RUN useradd -u 1000 -m -s /usr/sbin/nologin appuser \
&& chown -R 1000:1000 /app
USER 1000

# Health check
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

# Expose port
EXPOSE 8000

# Entry point
CMD ["python", "start_api_server.py"]
runAsNonRoot / readOnlyRootFilesystem assumptions

The marketplace runtime enforces runAsNonRoot: true. A Dockerfile with no USER (runs as root), or one that uses a name like USER appuser, is rejected at startup with container has runAsNonRoot and image will run as root. Always specify a numeric UID (e.g. USER 1000). Also, under readOnlyRootFilesystem: true, temporary writes (e.g. /tmp for file sharing) fail — mount /tmp as an emptyDir or point writes at a writable volume.

requirements.txt
agenticstar-platform[all]==0.5.29
fastapi>=0.115.0
uvicorn>=0.34.0
openai>=1.60.0
qdrant-client>=1.10.0

If your Kubernetes cluster runs on AMD64 architecture, make sure to specify --platform linux/amd64 when building.

Step 2: Docker Build & Push

curl
# Build
docker build --platform linux/amd64 \
-t your-acr.azurecr.io/my-agent:v1.0.0 .

# Login to ACR
az acr login --name your-acr

# Push
docker push your-acr.azurecr.io/my-agent:v1.0.0

Step 3: Agent Configuration File

config.toml is the file the SDK modules (DB / RAG / memory) read to build their connection info. Since PostgreSQLConfig.from_toml() and friends read this file to construct their config, your agent needs a config.toml (bundle it into the container image you build). For how to create it, see Quickstart — Step 2: Create the Configuration File.

config.tomlToml
# [agent] is metadata; the SDK does not read it (optional)
[agent]
name = "my-custom-agent"
version = "1.0.0"
description = "Custom agent"
port = 8000

# [database] is read by PostgreSQLConfig.from_toml() (required)
[database]
host = "${POSTGRESQL_HOST}"
port = 5432
database = "${POSTGRESQL_DATABASE}"
username = "${POSTGRESQL_USER}"
password = "${POSTGRESQL_PASSWORD}"
use_azure_ad = true

[database.azure_ad]
tenant_id = "${AZURE_TENANT_ID}"
client_id = "${AZURE_CLIENT_ID}"
client_secret = "${AZURE_CLIENT_SECRET}"

from_toml() only reads the sections for the modules you use — by default [database] (not [postgresql]; the field is username), plus [database.azure_ad] when use_azure_ad = true, and [memory] / [rag.embedding] / [rag.qdrant] when used. [agent] is metadata the SDK does not read (name / port etc. are set in the Console).

No default path: from_toml("config.toml") reads exactly the path you pass, so keep config.toml in the agent's working directory, bundle it into the image, and pass its path. (The auth config AgenticStarAuthConfig.from_config() additionally auto-detects config.toml in the current directory, then the project root, when no path is given.) Use ${VAR_NAME} placeholders instead of literal values; from_toml() expands ${VAR} / ${VAR:-default} from os.environ at load time (stdlib tomllib, no external toml).

Register the env vars your config.toml references (POSTGRESQL_* / AZURE_*) under [Agent Settings → Environment Variables]. Only context vars (EXECUTION_ID, USER_ID, …) are auto-injected.

Step 4: Platform Registration

  1. Log in to the admin console — Access the AGENTIC STAR Console
  2. Agent management screen — Navigate to "Agents" then "New Registration"
  3. Enter basic information (see Settings Guide — Agent Settings):
FieldValueDescription
Agent Namemy-custom-agentUnique identifier (alphanumeric and hyphens)
Display NameMy Custom AgentName displayed in the UI
Container Imageyour-acr.azurecr.io/my-agent:v1.0.0Full registry path
Port8000Port exposed by the container
Health Check Path/healthEndpoint checked by Kubernetes
  1. LLM Settings — Configure the Azure OpenAI model and endpoint to use (see Settings Guide — LLM Settings)
  2. Resource Settings — Configure CPU / memory requests and limits (see Settings Guide — Resources)
  3. Save & Deploy

Step 5: Verification

Verify via API Endpoint

curl
# Health check
curl https://your-platform.example.com/agents/my-custom-agent/health

# Chat request
curl -X POST https://your-platform.example.com/conversation/v1/chat/completions \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"model": "my-custom-agent",
"messages": [{"role": "user", "content": "Hello"}],
"stream": true
}'

For how to obtain <access_token>, see Marketplace Quickstart — Step 2: Obtain Token.

Verify via Chat Web App

  1. Access the Chat Web App
  2. Select "My Custom Agent" from the agent selection dropdown
  3. Send a message to verify operation

Pod Lifecycle

Using the SDK's PodRuntime class, you can notify the platform of Pod startup and shutdown states. The da (DataAccess instance) and execution_id used in the example below are the ones set up in SDK Quickstart — Step 3: Implement the Agent.

start_api_server.pyPython
import os
from kubernetes import client, config
from agenticstar_platform.db.pod_runtime import PodRuntime

# Self scale-down handler: delete this execution's SandboxClaim (its Sandbox and Pod go with it by cascade)
async def scale_down_self(execution_id: str) -> None:
config.load_incluster_config()
client.CustomObjectsApi().delete_namespaced_custom_object(
group="extensions.agents.x-k8s.io",
version="v1beta1",
namespace="marketplace-agents",
plural="sandboxclaims",
name=os.environ["HOSTNAME"], # the SandboxClaim shares the Pod's name
)

# Initialize with a DataAccess instance (da), execution_id, and pod_name
runtime = PodRuntime(
da,
execution_id=execution_id,
pod_name=os.environ.get("HOSTNAME", "unknown"),
scale_down_callback=scale_down_self,
)

# Notify Pod startup
await runtime.start()

# --- Agent processing ---

# Notify Pod shutdown. Updates status in DB; scales the Pod down if scale_down_callback is set
await runtime.final(status="completed")

Troubleshooting

SymptomCauseSolution
Pod is in CrashLoopBackOffFailed to load config.tomlVerify that environment variables are correctly injected
DB connection timeoutCannot reach PostgreSQL over the networkCheck NetworkPolicy and Service configuration
Health check failure/health endpoint not implementedAdd a /health route to FastAPI
Image pull errorRegistry authentication failedCheck imagePullSecrets configuration

Next Steps

Architecture Guide

SDK module structure and design philosophy

View guide

SDK API Reference

Complete specifications for all modules, classes, and methods

View guide