Deployment model
Construct runs locally for individual users or is deployed centrally for shared team usage. Three modes: solo, team, enterprise.
Construct is a deployable AI R&D operating system. It runs locally for individual users (the default) and can be deployed centrally for shared team or enterprise usage with shared memory, telemetry, queues, artifacts, policies, and execution resources.
The deployment posture is explicit. One config field (CONSTRUCT_DEPLOYMENT_MODE) selects the topology, and the rest of the system reads from there. The three modes are listed below.
For individual work. State lives in the repo and ~/.construct/. Postgres and Docker are optional accelerators.
- Queue
- filesystem .construct/intake/
- Memory
- local .construct/observations/
- Database
- optional Postgres
- Telemetry
- local JSONL traces
- Workers
- in-process
- MCP
- direct
For a development team. Postgres-backed queue with row-locked workers. Centralized telemetry and brokered MCP (staged/experimental, tracked: construct-9oi4.10).
- Queue
- Postgres FOR UPDATE SKIP LOCKED
- Memory
- shared per-user scope
- Database
- shared Postgres + pgvector
- Telemetry
- Langfuse / HTTP / OTel
- Workers
- Docker worker pool
- MCP
- brokered, role policy (staged/experimental, tracked: construct-9oi4.10)
Team mode plus tenant isolation, RBAC/ABAC auth, signed MCP allowlists, and mandatory audit events.
- Queue
- Postgres, tenant-scoped
- Memory
- shared, RBAC + ABAC
- Database
- shared Postgres + pgvector
- Telemetry
- mandatory audit events
- Workers
- isolated containers
- MCP
- signed allowlist + brokered (staged/experimental, tracked: construct-9oi4.10, construct-9oi4.1.7)
The agent loop (persona, specialists, contracts, gates) is the same across all three. Only the backend topology changes.
Modes
| Mode | Intended use | Queue | Memory | Database | Telemetry | Workers | Policy | MCP |
|---|---|---|---|---|---|---|---|---|
solo (default) | Individual usage | filesystem | local | optional | optional | local | lightweight | direct |
team | Shared usage | postgres | shared | postgres | central | docker | server-side | brokered (staged/experimental) |
enterprise | Hardened usage | postgres | shared | postgres | central | isolated containers | enforceable, audited | brokered + signed (staged/experimental) |
Solo
For individual work. State lives in the user's repo and ~/.construct/. Queue is the filesystem under .construct/intake/. Postgres and Docker are optional accelerators. Trace capture is local JSONL by default under .construct/traces/; remote telemetry export is opt-in.
Team
For shared usage by a development team. The intake queue is Postgres-backed (with row-locked worker claims). Memory is shared across the team. Workers run in a Docker pool, isolated from the host. Telemetry is centralized via a Langfuse-compatible backend, a generic HTTP ingestion endpoint, or an OpenTelemetry collector. MCP calls go through a broker that applies role-based policy — brokered MCP dispatch is staged/experimental and not yet active in built-in deployments (tracked: construct-9oi4.10).
A reference compose topology ships at docker-compose.team.yml: Postgres + a worker pool sized via CONSTRUCT_WORKER_REPLICAS, with the worker image built from Dockerfile.worker. The worker entrypoint (lib/worker/entrypoint.mjs) claims pending intake items via PostgresIntakeQueue.claim() (FOR UPDATE SKIP LOCKED), runs each through runJob with allowedPaths: [/work] so the bind-mounted workspace is the only writable surface, attaches evidence to the originating task graph node when named in the packet, and exits when the queue stays empty for --idle-timeout-seconds (default 300s) so a scheduler can scale workers to zero. Local verification lives at dev/team-harness/verify.sh; it expects DATABASE_URL/CONSTRUCT_DATABASE_URL, applies migrations, reads worker/queue health, and runs the focused team-mode tests.
Enterprise
Team mode plus tenant isolation, signed MCP allowlists, RBAC/ABAC-ready auth, isolated worker containers with policy-enforced workspace boundaries, retention controls, and mandatory audit events for every brokered call. Designed for environments where the orchestration surface and the data it touches both need explicit governance. Brokered MCP dispatch and signed allowlists are staged/experimental and not yet active in built-in deployments (tracked: construct-9oi4.10).
Picking and changing modes
construct config # show the active mode and resource topology
construct config mode # print just the active mode
construct config mode team # set the mode (writes ~/.config/construct/config.env)
The mode is persisted as CONSTRUCT_DEPLOYMENT_MODE in ~/.config/construct/config.env. construct status shows the active mode and resource topology at the top of its output.
What runs in each mode (capability matrix)
| Capability | Solo default | Team / enterprise default |
|---|---|---|
| LLM inference | local server (Ollama, llama.cpp, any OpenAI-compatible) or hosted provider | hosted provider; local fallback configurable |
| Embedding model | @huggingface/transformers ONNX in-process | shared embedding service or hosted |
| Vector retrieval | Postgres + pgvector when present; .construct/observations/ JSON index otherwise | shared Postgres + pgvector |
| Trace observability | local .construct/traces/*.jsonl; optional Langfuse/HTTP/OTLP export | central Langfuse-compatible backend, HTTP ingestion endpoint, or OTel collector |
| Issue tracking | bd (beads), Dolt-backed | bd against shared Dolt remote |
| Dashboard | construct dev starts the local dashboard | dashboard server in the shared deployment |
| MCP | local processes | brokered through mcp-broker (staged/experimental — not yet active in built-in deployments) |
| Intake queue | .construct/intake/ files | construct_intake_items table in Postgres |
| Session state | .construct/context.md, .construct/handoffs/, beads | shared state with per-user scoping |
Degraded-mode guarantees
Construct degrades gracefully when an optional resource is unreachable and reports the degradation explicitly rather than silently masking it.
- No Docker: managed Postgres is skipped; vector retrieval falls back to the JSON index. Local trace capture still writes
.construct/traces/*.jsonl.construct doctorreports which capabilities are degraded. - No
cm(memory CLI): the memory MCP server doesn't start; observations still write to.construct/observations/and remain retrievable from there. - No
OPENAI_API_KEY: ifCONSTRUCT_EMBEDDING_MODEL=openai, the command exits with the env var name and an alternative. Opt into automatic fallback withCONSTRUCT_EMBEDDING_FALLBACK=1. - No internet: Construct refuses to fetch external resources.
construct evals retrievalruns against the local fixture and works offline.
A degraded mode that silently masks the degradation is worse than one that announces itself.
Why explicit modes
Three concrete cases:
- Plane wifi (solo mode). You can still plan, write code, run tests, and have a coherent agent conversation. The vector index uses whatever you embedded locally; the LLM is whichever local model you wired up.
- A vendor outage (any mode). Falling back to a local model or to a different OpenAI-compatible endpoint is a config change, not a rewrite.
- A team that needs centralized telemetry and policy. Team mode promotes the intake queue, memory, and MCP through shared resources without changing the agent loop or the persona contracts.
The orchestration loop (persona, specialists, contracts, gates, durable state) is the same across modes. What changes is the backend topology that supports it.
What remains remote even in team mode
A few capabilities depend on external systems by their nature:
- Hosted telemetry retention. The local telemetry stack works for development and team use; long-term hosted retention is the cloud product.
- Provider integrations to remote systems. Slack messages, Jira issues, Salesforce records. The provider plugins are local code; the systems they talk to are remote.
- GitHub Actions / forge CI. Required-status-checks live on the forge. Construct's local gates are designed to catch what CI would catch; the forge gate is the final say.
These are integrations, not core dependencies. The orchestration loop runs without any of them.
How to verify the active mode
construct config
construct status
construct doctor
construct config prints the resolved deployment mode and resource topology. construct status shows them inline at the top of the health report and, in team/enterprise mode, includes queue depth, dead-letter depth, active workers, and stale workers. construct doctor reports degraded vs healthy across every cloud/local boundary; missing Postgres in team/enterprise mode is red, while DLQ/stale-worker findings are yellow degraded states with a one-line explanation.
CONSTRUCT_EMBEDDING_MODEL=hashing construct evals retrieval
Runs the retrieval eval with the deterministic, dependency-free embedding. Should report Recall@1: 100.0% against the local fixture: proof of a working retrieval pipeline that needs no external network call.