# Agents template (/agents-template)



## Why the foundation matters [#why-the-foundation-matters]

Agents follow the patterns around them. Crucible starts every project with a disciplined application stack, durable agent runtime, deployment path, and repository guidance, so generated changes begin inside production-ready boundaries instead of a blank repository.

## What it includes [#what-it-includes]

The foundation is one connected system, not a menu of packages. Each layer gives the agents working on top of it a stronger production boundary.

```mermaid
flowchart TD
  FE[Frontend] -->|chat APIs| BE[Backend]
  subgraph Runtime[Agent runtime]
    T[Temporal] -->|runs activities| WK[Worker]
  end
  BE -->|starts workflows| T
  subgraph Data
    PG[(Postgres)]
    R[(Redis)]
  end
  BE --> Data
  WK --> Data
  subgraph Path[Model and sandbox path]
    GW[LLM Gateway]
    SB[Sandbox session]
  end
  WK --> Path
```

* **Application foundation**
  * React, TypeScript, Vite, Tailwind, and Ciridae UI on the frontend
  * FastAPI, SQLAlchemy, and Alembic on the backend
  * Postgres, object storage, auth, and deployment infrastructure
* **Agent runtime**
  * Agents built on the OpenAI Agents SDK
  * Temporal workflows keep long-running agent work durable across retries and restarts
  * A dedicated worker polls Temporal and runs agent activities, including model calls and sandbox tool work
  * Redis carries chat control messages and stream fanout
  * Postgres stores threads, transcripts, queued messages, and sandbox sessions
* **Model and sandbox path**
  * The backend exposes authenticated chat APIs, starts agent workflows in Temporal, and streams events to the frontend
  * [LLM Gateway](/llm-gateway/) routes model calls and applies fallback policy
  * Each chat thread gets its own sandbox session for tool work
* **Runtime surfaces**
  * Docker Compose starts Postgres, backend, frontend, worker, Temporal, and Redis together
  * Workspaces and lite deployments use the same Compose-based startup contract
  * Full deployments provision the application, worker, data, network, and observability path
* **Repository guidance**
  * `AGENTS.md` and `REVIEW.md` files throughout the repository tell agents and reviewers how each area works
  * Agent skills under `skills/`
  * GitHub Actions checks for code quality, OpenAPI and API client drift, and database tests

## Work locally [#work-locally]

Open [Work locally](/work-locally/) to copy the managed environment values and start the full application and agent runtime together through Docker Compose.

## Plan private network ranges [#plan-private-network-ranges]

If a [full deployment](/deployments/full-deployment/) will connect to another network, choose its private address space before the first deployment. Each environment needs ranges that do not overlap existing or planned peers, VPN routes, on-premises networks, or other environments. That includes the cluster's internal pod and Kubernetes Service ranges, even though they are not advertised as peer routes. Renumbering after provisioning can require replacing network resources.

<Accordions>
  <Accordion title="Under the hood: required ranges and default sizes">
    Sizes are total IPv4 addresses. Cloud providers reserve some addresses inside each subnet, so the usable count is lower.

    <Tabs items="[&#x22;GCP&#x22;, &#x22;Azure&#x22;, &#x22;AWS&#x22;]">
      <Tab value="GCP">
        * **Network and data ranges**: The defaults are app subnet `10.0.0.0/24` (256 addresses), GKE nodes `10.2.0.0/24` (256), and backend connector `10.8.0.0/28` (16). Cloud SQL private service access also requires a separate `/16` (65,536).
        * **Cluster-internal ranges**: GKE uses `10.4.0.0/14` (262,144 addresses) for pods and `10.9.0.0/20` (4,096) for Kubernetes Services. Cloud NAT keeps these ranges off public internet egress, but they still must not overlap connected networks: cluster routing can intercept a matching destination, and pod addresses can remain unmasqueraded on private traffic.
        * **Allocation guidance**: Reserve a unique contiguous `/13` or larger parent block per environment, then carve all six ranges from it. A `/13` is a planning recommendation, not a provider requirement. The Terraform module lets Google choose the Cloud SQL `/16` automatically; deterministic peering plans should pin that address before the first apply. The generated environment root does not expose the remaining CIDR settings, so thread custom ranges through the environment, deployment, and VPC modules.
      </Tab>

      <Tab value="Azure">
        * **VNet and subnet ranges**: The default VNet is `10.40.0.0/16` (65,536 addresses). It contains the AKS node subnet `10.40.0.0/22` (1,024), PostgreSQL subnet `10.40.4.0/24` (256), private endpoint subnet `10.40.5.0/24` (256), and AKS API server subnet `10.40.6.0/28` (16).
        * **Cluster-internal ranges**: The AKS module does not set these values, so Azure CNI Overlay supplies `10.244.0.0/16` (65,536 addresses) for pods and `10.0.0.0/16` (65,536) for Kubernetes Services. Outbound SNAT keeps these ranges off public internet egress, and overlay pod addresses do not consume VNet addresses. They still must not overlap connected networks because cluster routing can intercept a matching destination.
        * **Allocation guidance**: Assign a unique `/16` VNet to every environment and keep all four subnets inside it. Reserve separate, non-overlapping cluster-internal ranges outside the VNet. The CIDRs default inside the Azure deployment module and are not exposed by the generated environment root, so thread custom values into that module before the first apply.
      </Tab>

      <Tab value="AWS">
        * **VPC and subnet ranges**: The default VPC is `10.0.0.0/16` (65,536 addresses). With the default two availability zones, it contains worker subnets `10.0.0.0/20` and `10.0.16.0/20` (4,096 each) and database subnets `10.0.240.0/24` and `10.0.241.0/24` (256 each).
        * **Cluster-internal ranges**: The VPC CNI gives each pod an address from the worker subnets, so pods need no separate range. The EKS module does not set the Kubernetes Service range, so EKS assigns `10.100.0.0/16` or `172.20.0.0/16` (65,536 addresses) based on the VPC range. It still must not overlap connected networks because cluster routing can intercept a matching destination.
        * **Allocation guidance**: Assign a unique `/16` VPC to every environment; the VPC module requires a `/16`. The CIDR defaults inside the AWS VPC module and is not exposed by the generated environment root or the deployment module, so thread a custom `vpc_cidr` through before the first apply.
      </Tab>
    </Tabs>
  </Accordion>
</Accordions>
