Skip to content

middle-core — build & deploy

The same lane as the other AgentArmy spokes (frontend-core / backend-core): a container that runs locally on Docker and ships to Azure Container Apps (dev) on push to main. The service listens on port 8001 and serves /health.

Local Docker (localhost)

# compose (recommended)
docker compose up --build           # -> http://localhost:8001/health

# or plain docker
docker build -f templates/middle-core/Dockerfile -t middle-core:dev .
docker run --rm -p 8001:8001 middle-core:dev

The Dockerfile bakes in templates/business-object-catalog.example.json as the default catalog (/app/catalog.json). In dev/prod, override it with the BUSINESS_OBJECT_CATALOG env var (or a Container Apps secret) pointing at the real catalog.

Azure Container Apps (dev cloud)

CD is driven by .github/workflows/middle-core-AutoDeployTrigger.yml: every push to main builds the image and deploys it to the middle-core Container App. It targets the same registry and resource group as the other spokes:

  • registry: arcadeplatformacr.azurecr.io
  • resource group: rg-arcade-platform
  • container app: middle-core · ingress external · target port 8001

One-time provisioning (owner, Azure-authenticated)

# reuse the same Container Apps environment as the other spokes
ENV=$(az containerapp env list -g rg-arcade-platform --query "[0].name" -o tsv)

az containerapp create \
  --name middle-core --resource-group rg-arcade-platform --environment "$ENV" \
  --image arcadeplatformacr.azurecr.io/middle-core:bootstrap \
  --target-port 8001 --ingress external \
  --registry-server arcadeplatformacr.azurecr.io

Then add the repo secrets the workflow reads (do not run az containerapp github-action add — this repo ships its own trigger workflow, so that would create a duplicate):

Secret Value
MIDDLECORE_AZURE_CLIENT_ID OIDC app registration (federated credential for this repo)
MIDDLECORE_AZURE_TENANT_ID Azure tenant id
MIDDLECORE_AZURE_SUBSCRIPTION_ID Subscription id
MIDDLECORE_REGISTRY_USERNAME ACR username (or admin user)
MIDDLECORE_REGISTRY_PASSWORD ACR password

After provisioning, push to main (or run the workflow manually) and the app builds and deploys automatically — same as the other spokes.


agent-runtime (Python CopilotKit service)

The agent_runtime/ service is the Python CopilotKit agent runtime. It listens on port 8100 and exposes /health and /copilotkit. The frontend-core service points at it via the COPILOTKIT_RUNTIME_URL env var (paired with frontend-core issue #27).

Local Docker (localhost)

# Start both middle-core and agent-runtime together
docker compose up --build

# agent-runtime is then reachable at:
#   http://localhost:8100/health      -> {"status":"ok"}
#   http://localhost:8100/copilotkit  -> CopilotKit endpoint

Set your Cerebras API key before starting (never commit it):

export CEREBRAS_API_KEY=your-key-here
docker compose up --build

All other env vars have working dev defaults in docker-compose.yml (CEREBRAS_MODEL, CEREBRAS_BASE_URL, LLM_PROVIDER, BACKEND_CORE_URL, CORS_ORIGINS). Override any of them the same way.

Azure Container Apps (dev cloud)

The Bicep definition is at deploy/aca-agent-runtime.bicep. Deploy parameters:

Parameter Default Notes
containerAppsEnvironmentName arcade-platform-env Reuse existing ACA env
imageName arcadeplatformacr.azurecr.io/agent-runtime:latest Tag set at deploy time
registryServer arcadeplatformacr.azurecr.io Same ACR as other spokes
cerebrasApiKey (required, @secure()) Pass from Key Vault or CI secret — never hard-code
cerebrasModel llama-3.3-70b Override to change model
cerebrasBaseUrl https://api.cerebras.ai/v1 Cerebras API base
llmProvider cerebras LLM provider selector
backendCoreUrl http://backend-core Internal ACA env URL for backend-core
corsOrigins http://localhost:3000 Set to frontend-core FQDN in dev/prod

One-time provisioning (owner, Azure-authenticated)

ENV=$(az containerapp env list -g rg-arcade-platform --query "[0].name" -o tsv)

az deployment group create \
  --resource-group rg-arcade-platform \
  --template-file deploy/aca-agent-runtime.bicep \
  --parameters \
    containerAppsEnvironmentName="$ENV" \
    cerebrasApiKey="$(az keyvault secret show --vault-name <kv-name> --name cerebras-api-key --query value -o tsv)" \
    backendCoreUrl="https://backend-core.<env-fqdn>" \
    corsOrigins="https://frontend-core.<env-fqdn>"

Add the required GitHub Actions repo secrets for the CD workflow (mirrors the middle-core pattern):

Secret Value
AGENTRUNTIME_AZURE_CLIENT_ID OIDC app registration (federated credential)
AGENTRUNTIME_AZURE_TENANT_ID Azure tenant id
AGENTRUNTIME_AZURE_SUBSCRIPTION_ID Subscription id
AGENTRUNTIME_REGISTRY_USERNAME ACR username
AGENTRUNTIME_REGISTRY_PASSWORD ACR password
CEREBRAS_API_KEY Cerebras API key (projected into ACA secret at deploy time)

Manual follow-up required: /health and /copilotkit reachability in dev requires an actual cloud deploy by the repo owner. No cloud credentials are present in the agent worktree. After provisioning, verify with:

FQDN=$(az containerapp show -n agent-runtime -g rg-arcade-platform --query properties.configuration.ingress.fqdn -o tsv)
curl https://$FQDN/health
# expected: {"status":"ok"}