Platform Architecture
Resolve is a multi-repo autonomous code generation platform. Its architecture separates concerns across a clear boundary: the platform host (FastAPI backend) owns infrastructure — container lifecycle, event routing, API surface. The resolver (plugin process) owns semantics — what to build, how to build it, what the output means.
System diagram
Section titled “System diagram”Component responsibilities
Section titled “Component responsibilities”Platform host
Section titled “Platform host”The backend owns all infrastructure concerns. It provides mechanisms, never policies.
| Component | File | Responsibility |
|---|---|---|
| Routes | routes/instances.py, routes/resolvers.py |
REST API for all consumer interactions |
| Orchestrator | orchestrator.py |
Container lifecycle: create, setup, launch, poll, cancel, resume |
| Monitor | monitor.py |
Background loop: mirror events, discover input-requests, extract state |
| InstanceStore | storage.py |
Persist instance records and status |
| EventBus | internal | Fan-out SSE events to connected consumers |
| ManifestRegistry | plugins/manifest.py |
Load resolver catalog from resolvers.json |
| ContainerProvider | containers/ |
Incus-first, Docker-fallback container operations |
| AuthMiddleware | auth.py |
Bearer token validation |
| Broker | broker/ |
Reality-check orchestration: DTU environments, runner lifecycle |
Resolver (plugin process)
Section titled “Resolver (plugin process)”The resolver runs inside the worker container as a separate process. It owns all semantic concerns:
| Responsibility | Description |
|---|---|
| Instantiation schema | What fields to ask for when creating an instance |
| Workspace setup | Which repos to clone, which branch to work on |
| Business logic | What run() does — all planning, implementation, verification |
| Event emission | What events to emit and when (phase, artifact, completion) |
| Input requests | When to pause and ask the user for input |
| Message handling | What unsolicited messages to accept and how to respond |
| Output artifacts | PR URLs, branch names, reports, summaries |
Three A2UI interaction surfaces
Section titled “Three A2UI interaction surfaces”A2UI v0.9 is the wire format for all three surfaces. The platform validates incoming payloads against check rules; the resolver interprets semantic meaning.
Data bus: on-demand file serving
Section titled “Data bus: on-demand file serving”Resolver writes: /project/.resolve/data/graph.dot /project/.resolve/data/progress.json /project/.resolve/data/nodes/abc123/response.md
Consumer fetches: GET /instances/{id}/data/graph.dot GET /instances/{id}/data/progress.json GET /instances/{id}/data/nodes/abc123/response.md
Resolver signals: resolver.data_changed ← event with affected pathsViewport reacts: fetchData(path) per each changed pathData is never pushed — never polled — always fetched on demand. The resolver signals what changed; consumers decide what to re-fetch.
Container runtime
Section titled “Container runtime”The platform uses Incus as the primary container runtime for all worker containers and sidecars in local and DTU deployments. Docker is supported as a fallback and for future remote deployments.
detect_runtime() ├── incus available? → use IncusProvider └── docker available? → use DockerProvider (fallback)Container naming:
| Container | Purpose |
|---|---|
resolve-{id} |
Main resolver container for instance {id} |
resolve-{id}-gitea |
Gitea sidecar (when capabilities_required: ["gitea"]) |
resolve-{id}-env-{uuid} |
Ephemeral sub-container for sandboxed steps |
Two startup paths
Section titled “Two startup paths”Cached fast path (~15 seconds): Image: amplifier-cache:python Has: uv, Python env, pre-installed common packages Setup: install resolver + SDK from cache or GitHub, write config
Cold path (~5 minutes): Image: ghcr.io/astral-sh/uv:python3.13-trixie-slim Has: bare Python Setup: apt packages, CLI tools, provider SDKs, pipeline engine, git identity/auth, repo clone, bundle activationThe platform selects the fast path when amplifier-cache:python exists locally.
Build it once:
cd amplifier-resolvebash scripts/build-cache-image.shRequest lifecycle: POST /instances
Section titled “Request lifecycle: POST /instances”Platform vs resolver: the bright line
Section titled “Platform vs resolver: the bright line”The platform validates structure, never interprets meaning.
| Concern | Platform | Resolver |
|---|---|---|
| Container create/start/stop/destroy | ✓ | |
| A2UI schema validation | ✓ struct. only | ✓ semantic meaning |
| Input request storage + routing | ✓ | ✓ schema + handling |
| Message delivery | ✓ | ✓ catalog + handling |
| LLM session creation | ✓ factory | ✓ what to ask |
| Event streaming | ✓ mirror + SSE | ✓ what to emit |
| Repo cloning | ✓ mechanics | ✓ which repos |
| Business logic | ✓ everything |
If two teams could want different behavior → it’s a resolver concern, not a platform concern.
Key source files
Section titled “Key source files”| File | Role |
|---|---|
app.py |
FastAPI app: routes, middleware, lifespan, monitor start |
routes/instances.py |
Instance CRUD, events, input-requests, messages, data |
routes/resolvers.py |
Resolver discovery, schema endpoints |
orchestrator.py |
Container lifecycle: create, inject, launch, poll, cancel |
monitor.py |
Background loop: event mirror, input-request discovery, status |
storage.py |
InstanceStore: persistent instance state |
auth.py |
AuthMiddleware: bearer token validation |
containers/incus.py |
Incus container provider implementation |
broker/reality_check.py |
Reality-check orchestration via broker |
core/resolve_worker.py |
Container-side worker entry point |
core/resolve_core.py |
Dispatches to selected resolver implementation |
core/resolver.py |
Resolver Protocol + ResolverResult |
core/events.py |
EventEmitter: structured event writing + state |
plugins/manifest.py |
ManifestRegistry: resolver catalog management |