One guarded door into the twin, for every caller.
The reasoning service is the part of NovusLens that people and tools talk to when they want something from the twinTwinNovusLens’s model of one organisation, built from records about its teams, services and how they rely on one another. It is only as current as those records.. The web application proxiesProxyA service that receives a request and forwards it to another service. The NovusLens web proxy adds the signed-in identity and service token. browser requests to it. Trusted evidence producers can call the service directly. It reads the PostgresPostgresThe database software that stores the tables read by the NovusLens screens, along with document bodies, access records and protected personnel records. read modelRead modelThe database tables used by the map, Ask and Find. NovusLens rebuilds these tables from its history of recorded changes. and writes observations through the shared meshMeshA set of connected Mycelium services that exchange updates and keep the NovusLens log. commit path. A local language modelLanguage modelSoftware that produces text from instructions and supplied context. NovusLens checks its answers against the records retrieved for the question. composes answers, checked against retrieved records.
What it is for
A leader asks “where is our critical pathCritical pathThe dependency chain with the greatest total coordination weight in the map. It identifies a structural constraint. It does not state elapsed time. longest?” in Compass. A steward retracts a findingFindingA difference in the records that needs a decision. It includes its sources and can describe a slow handoff, disputed fact or missing owner. raised in error. An operator publishes a set of evidence records for C/A/RC/A/RThree separate scores for a team or service: Complexity, Agility and Recoverability. Each uses current evidence and the customer’s stated scoring rules. (Complexity, Agility and RecoverabilityRecoverabilityThe R in C/A/R: how well a team or service restores acceptable service after a failure. Recovery times and tested alternatives can supply evidence.). An integrator sends signed agent evidence. All four reach this service through the same checks. The service looks up the viewer account’s role and the cellsCellA box on the map that stands for a team, service, supplier or AI agent. It is a unit you can inspect, not necessarily a department or a person. it may see. The call is audited, and verdict wording is withheld.
The service maps, surfaces and advises. It does not run, gate or roll back anything in the customer’s agent estateAgent estateThe collection of AI agents an organisation operates, together with the systems and providers they use..
How it starts
The Compose reasoning service runs conway_reasoning.serve --host 0.0.0.0 --mesh-host mesh-0 on port 8500. Its health check requests /health. The ui service publishes the user-interface port, 3111 by default. Run by hand, main() in serve.py takes four options.
| Option | Default | Meaning |
|---|---|---|
--port | 8500 | Port the service listens on. |
--host | 127.0.0.1 | Bind address. Compose sets 0.0.0.0 inside its private application network. |
--mesh-host | 127.0.0.1 | Host of the mesh gatewayGatewayA service that accepts requests and passes them into another system. The Mycelium gateway gives NovusLens access to the mesh.. |
--mesh-port | 8400 | Port of the mesh gateway. |
The module defaults to 127.0.0.1. The Docker demo selects --host 0.0.0.0 inside its private network and publishes no reasoning host port. The shared service tokenService tokenA secret value sent with requests between NovusLens services. The receiving service refuses requests with a missing or wrong value. remains required in the customer profileDeployment profileA setting that selects customer or development behaviour. Customer mode refuses development credentials and uses the signed-in session as the identity..
On start, main() does these things in order:
- It calls
require_customer_safeforCONWAY_SERVICE_TOKENandMYCELIUM_GATEWAY_TOKEN. In the customer profile the process exits at once if either is unset or still a known development value. - It decides whether to register the MCPMCPModel Context Protocol: a standard way for an AI application to discover and call named tools supplied by another program. tools on the mesh gateway. In the dev profile it does. In the customer profile it does not, unless
NOVUSLENS_MCP_EXPOSE=1. - When registering, it tries up to 30 times, one second apart, until the gateway answers, then starts a background thread that serves MCP invocations. If the gateway never answers, the service exits.
- It starts uvicorn on the port.
When the development variable CONWAY_AGENT_EVIDENCE_CONFIG is set, the service also starts an agent-evidence delivery worker inside its lifespan and stops it on shutdown. A customer host does not set it: there, the projectionProjectionThe regular pass that brings the read model up to date with the canonical log. It runs every 30 seconds by default. worker delivers the agent-evidence outboxOutboxA database list of saved messages waiting to be published. A message stays on the list until its progress is recorded. on every pass that materialises cleanly (conway_reasoning/project.py). See agent accountability.
Profile and the service token
CONWAY_PROFILE is dev unless set to customer. In the customer profile, requests must carry x-conway-service-token matching CONWAY_SERVICE_TOKEN. /health and /ready are exempt. The token comparison takes the same time regardless of where its values differ; missing or wrong values return 401. The web application attaches the token to browser calls after taking the viewer from sign-in. Trusted command-line evidence producers also use the token. In development this call requires no service token. Requests with a body larger than 4 MiBKiB and MiBBinary size units: one KiB is 1,024 bytes; one MiB is 1,048,576 bytes. Evidence limits use these units. are refused with 413 in both profiles.
Dependencies
| Direction | What | How the code reaches it |
|---|---|---|
| Upstream caller | The web application | HTTPHTTPHypertext Transfer Protocol: the rules a browser or program uses to send a request to a web service and receive its response. to CONWAY_REASONING_URL, default http://127.0.0.1:8500, with the service token. |
| Downstream | Postgres read model | conway_graph.db.connect() reads DATABASE_URL; the customer profile refuses to fall back to a development URL. |
| Downstream | MyceliumMyceliumThe application infrastructure underneath NovusLens. Its connected services exchange updates and keep the ordered structural log. mesh gateway | NOVUSLENS_MESH_HTTP_ADDR and NOVUSLENS_MESH_HTTP_BASE, default 127.0.0.1:8400. Writes go through TwinWriter; MCP registration and invocations use the Python SDKSDKSoftware development kit: a package of code that helps another program use a service. NovusLens uses mycelium-py to talk to Mycelium.. |
| Downstream | Language model | An OpenAI-compatible chat endpointEndpointA particular address on a service that accepts a defined kind of request.. See below. |
| Peer | Projection worker | ./lens exec -- python -m conway_reasoning.project is a separate service in the same package. It rebuilds the read model on an interval and records each pass; /ready reads those records. |
The language model
Model calls go through chat in apps/mesh/src/conway_mesh/build_agent.py and the shared request helper. The endpoint is set by CONWAY_LLM_ENDPOINT; its default, http://localhost:11434/v1/chat/completions, uses local Ollama. The helper also supports OpenRouter when that exact endpoint is configured. See environment variables for the key and model settings. Compass uses CONWAY_COMPASS_MODEL (default qwen3:30b); Strategy uses CONWAY_STRATEGY_MODEL, falling back to the Compass model. Details are on asking and answering. When the model does not answer, the service returns 503 with a plain message that records and findings are unaffected.
Module map
All modules are in apps/reasoning/src/conway_reasoning/. The four architectural units below each have a page.
serve.py registers.project.py belongs to the projection worker rather than to the HTTP service, and is covered under the read model.
Failure behaviour
serve.py returns 503 with an explanation for four failures: mesh timeout, log divergence, unreachable model runtimeModel runtimeThe software that loads and runs an AI model so it can answer requests. and database error. Model requests are limited: at most 8 model-bound requests run at once across the process and at most 2 per viewer, and beyond that the service returns 429.
The web application, the reasoning service, Postgres, the mesh gateway and the configured model endpoint, with the direction and purpose of each call.