A task-declared multi-service example. The task ships its own
environment.compose.yaml declaring three services (runner + db-service +
a task-specific app-service), and the engine materialises them once at
run start under --runtime shared (Case B in
ADR-0018).
The agent's job is to query the running product-catalog HTTP service and write a short executive summary of the top-3 most expensive in-stock products.
- Task-authored
environment_manifestunder shared runtime — realistic environment (real running HTTP service the agent hits) without paying per-trial substrate cost. Contrast with the per-trial isolation path, which materialises a fresh substrate per trial. - Docker Compose service discovery inside the substrate. All services join
the same auto-generated docker-compose network, so the runner container
reaches
app-serviceby service name via docker DNS (http://app-service/products.jsonfrom inside the runner). - The
:localengine-image alias pattern the engine applies at run start, so task compose files can referencetolokaforge-runner:localandtolokaforge-db-service:localregardless of the underlying content-hash tag (seedocs/RUNTIME_BACKENDS.md).
uv run tolokaforge validate --tasks "examples/native/multi_service/dataset/**/task.yaml"scripts/with_env.sh uv run tolokaforge run --config examples/native/multi_service/run_configs/dev.yamlexamples/native/multi_service/
├── project.yaml # identity + task discovery + task_defaults
├── run_configs/dev.yaml # models + orchestrator + evaluation
├── README.md # this file
└── dataset/tasks/multi_service/
└── multi_service_example_01/
├── task.yaml # declares environment_manifest + tools
├── environment.compose.yaml # 3-service compose
├── grading.yaml # state checks + transcript rules
└── fixtures/
└── products.json # served by app-service (nginx)
isolation: shared_ok— the task tolerates state sharing across trials. Its grading only inspects the agent's output (a written file); the app-service is read-only static content that doesn't mutate.app-serviceis deliberately trivial — nginx serving a static JSON file. The point of the example is to demonstrate the multi-service materialisation path, not to be a realistic application. Real task packs would ship a proper backend + database + …- The runner reaches
app-serviceby service name. Docker Compose auto-networks all services in a compose file; container-name-based DNS resolution works from any service to any other on the same network.
- ADR-0018 — Case matrix + sequence diagrams for each supported case
- ADR-0016 — shared vs per_trial (lifecycle axis)
- docs/RUNTIME_BACKENDS.md — mechanics deep-dive