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

Execution Model​

A marketplace custom agent runs as a "one execution = one process" batch, not a long-running HTTP server.

  1. When a user sends a message, the platform starts the agent's Pod and injects the context variables (EXECUTION_ID / CONVERSATION_ID / USER_ID / MESSAGE_ID, etc.) as environment variables
  2. The process started by the container's CMD calls run_marketplace_agent(). The SDK runner handles fetching the input message → running your agent → persisting the result to the DB and notifying the webhook (delivering the terminal event exactly once)
  3. When processing finishes, the process exits with code 0 (the Pod does not stay resident)

Because of this, you do not need to expose a port, implement a /health endpoint, or use a web framework such as FastAPI. For how to write the agent function, see the "Run Marketplace-compatible (runner)" section of the SDK Quickstart.

Agents that run in workflow steps

Agents used in project workflows (Marketplace edition 3.1 and later) call agenticstar_platform.workflow.run() from the start command instead of run_marketplace_agent. When registering them in the admin console, enable "Use in workflows" and register a contract; they cannot be started in workflows until certification information such as the image digest is registered. See the Workflow Guide for details.

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

# Entry point (a one-shot process that calls run_marketplace_agent.
# Not a resident server — no port exposure or health-check endpoint needed)
CMD ["python", "marketplace_agent.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]==3.0.15
openai>=1.60.0
qdrant-client>=1.13.0

Use 0.5.30 or later for the default run_marketplace_agent configuration (the DB connection fallback used when data_access is omitted). 0.5.29 has a connection-construction bug that crashes with an AttributeError at startup unless you pass data_access= explicitly.

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"

# [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 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.0Registry, image name, and tag
Environment VariablesDB_HOST / DB_PASSWORD / WEBHOOK_URL etc.DB connection (PostgreSQLConfig.from_env() contract) and webhook target. Context variables (EXECUTION_ID etc.) are auto-injected and must not be registered (registering the same name is an error)
  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
# 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 Call the API — 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

Execution Lifecycle and Pod Management​

Pod lifecycle management (startup, execution-state recording, shutdown, cleanup) is the platform's responsibility. No agent-side implementation is required.

  • Execution state (the execution_pods table) is recorded by the Marketplace executor. Your agent does not need to call the SDK's PodRuntime (doing so would double-write against the executor's records; furthermore, Pods in the marketplace-agents namespace get no ServiceAccount token, so code that calls the Kubernetes API from inside the Pod will not work)
  • The terminal event (COMPLETION_SUCCESS / COMPLETION_FAILURE) is delivered exactly once by run_marketplace_agent(). Even when the agent function raises an exception, the runner delivers COMPLETION_FAILURE and then terminates the process normally
  • After processing completes, the process exits with code 0 and the platform cleans up the Pod
  • A cycle execution (a conversation the platform starts on a schedule) is not counted as completed just because it exits 0 ("finished, completion not measured"). To have it counted as a success, your agent reports completion with report_completion (v3.0.14+, see the Quickstart)

The PodRuntime class (SDK API Reference) is a building block for deployments that manage their own Pods outside the marketplace; it is not used by marketplace custom agents.

Troubleshooting​

SymptomCauseSolution
Pod keeps restartingThe process exits non-zero (restartPolicy: OnFailure restarts it)Check the logs for the error. Structure the agent to exit 0 after processing via run_marketplace_agent (do not start a resident server)
Pod is in CrashLoopBackOffFailed to load config.tomlVerify that environment variables are correctly injected
A cycle execution never finishes and the next trigger is skippedThe process stays alive after the work is done (still a server answering health checks). The platform decides that an execution has finished from the container exit codeClose the server and exit after the work completes ([Quickstart](/docs/marketplace/develop/quickstart/quickstart-sdk#exit-after-run))
Stops with MarketplaceRunnerFenceTaken (v3.0.12+)In a cycle execution, the pod was recreated after a previous runner had already started your agentNo action needed (the stop prevents running the same execution twice). The platform closes the execution as failed with unknown effects
Cycle executions are never counted as successes (result: "finished, completion not measured")Your agent does not report completion (a clean process exit is not treated as completion)Call report_completion at the end of your agent to report completion (v3.0.14+). The report is adopted only when the container exits 0
Stops with MarketplaceRunnerConfigErrorWEBHOOK_URL or a context variable (EXECUTION_ID etc.) is missingCheck that WEBHOOK_URL is registered under [Agent Settings → Environment Variables] (missing DB_* causes a connection error instead, not this error)
DB connection timeoutCannot reach PostgreSQL over the networkCheck NetworkPolicy and Service configuration
No response appears in ChatWEBHOOK_URL is unset or wrongCheck the WEBHOOK_URL environment variable
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