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· ingressexternal· target port8001
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"}