This guide walks through the 5 steps an agent follows to install and configure Steward. If ACS is already running, the agent skips straight to collaborating.
Pull and run the Steward Docker image. SQLite is used out of the box — no external dependencies.
# Clone the repo
# Pull the image
docker pull naharemete/steward_acs:latest
# Start (SQLite default — single container, no external deps)
docker compose up -d
# Verify it's alive
curl http://localhost:4001/mcp/healthThe agent can also configure options like LLM provider (for memory quality audits), semantic embeddings, and PostgreSQL. These are optional — ACS works with sensible defaults.
LLM Provider — Audits memory quality. Does NOT power the agent.
| Option | Trade-offs |
|---|---|
| None (default) | Memories auto-approve — no quality checks |
| NVIDIA NIM / MiniMax / MIMO / OpenAI | Quality checks, needs API key |
Semantic Embeddings — Search memories by meaning instead of keywords. Needs Ollama container + nomic-embed-text model.
Database — SQLite (default, single container) or PostgreSQL (production, concurrent).
If the user says "just make it work", the agent uses minimal defaults — no LLM, no embeddings, SQLite, no log streaming:
services:
steward_acs:
image: naharemete/steward_acs:latest
ports: ["4001:4001"]
env_file: .env
volumes:
- acs_data:/app/priv
volumes:
acs_data:The agent looks at what services are running in your project — checking docker-compose.yml and docker ps — to discover apps that should connect to ACS.
docker-compose.yml to find servicesdocker psConnect external apps so their APIs look like native MCP tools that agents can call directly. The agent asks for each app's name, URL, API key, and auth details, then configures the bridge at runtime or permanently via env vars.
Create a {app}.yaml file in the tools directory:
app: my_app
tools:
- name: my_tool
description: "What this tool does"
handler: ""
endpoint: "http://my-service:8080/api/my-tool"
category: custom
level: 1
inputSchema:
type: "object"
properties:
param1:
type: "string"
description: "..."Hot-reload with acs_refresh_tools() — no server restart needed.
Configure an external app so ACS bridges its API as MCP tools:
app_configure(
name: "my_app",
base_url: "http://my_app:5000",
api_key: "sk_...",
auth_endpoint: "/api/auth/validate-key",
auth_header_name: "authorization",
auth_header_scheme: "Bearer",
timeout_ms: 30000
)Make permanent by adding to .env-steward:
CONFIGURED_APPS=my_app
APP_MY_APP_URL=http://my_app:5000
APP_MY_APP_API_KEY=sk_...
APP_MY_APP_AUTH_ENDPOINT=/api/auth/validate-key
APP_MY_APP_AUTH_HEADER_NAME=authorization
APP_MY_APP_AUTH_HEADER_SCHEME=Bearer
APP_MY_APP_TIMEOUT_MS=30000Verify with app_list — should show the app with has_api_key: true.
Custom auth schemes:
| Auth pattern | Header name | Scheme |
|---|---|---|
Authorization: Bearer <key> (default) | authorization | Bearer |
X-API-Key: <key> | x-api-key | empty |
Authorization: Api-Key <key> | authorization | Api-Key |
Steward can ingest logs from your apps and expose them to agents via get_logs(). The agent sets this up based on whether your apps run in Docker or elsewhere.
Reads all Docker container stdout/stderr automatically. Adds a sidecar container:
fluent-bit:
image: cr.fluentbit.io/fluent/fluent-bit:3.1
environment:
LOG_INGEST_KEY: ${LOG_INGEST_KEY}
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
- ./parsers.conf:/fluent-bit/etc/parsers.conf:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:roFluent Bit reads every container's stdout/stderr — no per-app configuration needed.
Send log entries via HTTP POST to /api/logs/ingest with header X-Log-Ingest-Key: <KEY>:
POST /api/logs/ingest
X-Log-Ingest-Key: your-log-ingest-key
{
"message": "Something happened",
"level": "error",
"service": "my-app",
"component": "api/users",
"metadata": { "action": "create_user", "status": "ok" }
}Log entry fields:
| Field | Required | Default | Description |
|---|---|---|---|
message | Yes | — | The log text |
level | No | "info" | debug, info, warn, error, fatal |
service | No | "unknown" | App or service name |
component | No | "external" | Subsystem within the app |
metadata | No | {} | Arbitrary key-value data |
Batch multiple entries at once:
{
"logs": [
{ "message": "Started", "service": "app1", "level": "info" },
{ "message": "DB connected", "service": "app1", "level": "info" }
]
}Agents query collected logs with get_logs(service: "my-app", level: "error", search: "timeout").
With ACS running, apps connected, and logs streaming, the agent completes setup by registering with ACS:
acs_get_present_status(agent_id: "YourName") — introduces the agent to the system.acs_claim_work(agent_id: "YourName") — gets a guidance packet with project context and relevant memories.acs_create_work() — defines units of work with file paths.acs_lock_file() — prevents multi-agent edit conflicts.acs_save_memory() — preserves learnings across sessions.acs_list_error_traces() — monitors and resolves runtime issues.get_logs() — debugs using collected app logs.The agent is now fully integrated with Steward. All future agents that connect will read the AGENTS_STEWARD.md file to learn how to register and work in this project.