Draft. This document is a work in progress shared for early review. Content and diagrams may change before the final version.
docs / ARCHITECTURE

Fred Platform
Architecture

Component topology, data flows, storage boundaries, network layout, and the security perimeter — for platform engineers, security teams, and architects.

Scope & audience

This document answers the structural questions that the Developer Guide deliberately skips: how the components are wired together, what calls what over which protocol, where data lives, and where the security boundaries sit.

Primary audience: platform engineers sizing or hardening a deployment, security and compliance teams (RSSI, DSI) reviewing the attack surface, architects integrating Fred into a larger infrastructure.

Not covered here: developer onboarding, the contribution workflow, or the reading path through the codebase — those are in the Developer Guide. What each component does (APIs, formats, agents) is in the Feature Reference.

Logical architecture & core flows

Above the physical topology, Fred separates management from execution. The Control Plane is the sole authority for agentic-pod discovery, agent enrollment, session and metadata, and for resolving the execution URL the UI calls. Agentic pods — the bundled fred-agents and any custom team pods — authenticate each request themselves against the caller's Keycloak identity, run the agent logic, and stream results back over SSE. There is no signed grant or capability token in this path: the control plane issues none, and each pod authorizes every request itself with a per-request ReBAC (OpenFGA) check. Governance policies and ReBAC authorization apply across the whole path.

User Interface React · SSE client Keycloak / OIDC identity provider Control Plane pod discovery · agent enrollment sessions & metadata Temporal lifecycle worker Governance policies models · tools/MCP · prompts · agents · data ReBAC / OpenFGA authorization Agentic pods fred-agents + custom team pods fred-runtime · ReAct / Graph SSE streaming · checkpoints · HITL Model routing → LLM providers Tools — builtin · MCP · custom Knowledge Flow ingestion / retrieval · Temporal workers Stores PostgreSQL · OpenSearch · object storage (MinIO / GCS) — metadata, session history, checkpoints, vectors SSE stream REST + bearer enrollment · policy retrieval / ingestion login (OIDC) resolve policy select model

Management (Control Plane) is decoupled from execution (agentic pods). Retention/erasure and other lifecycle work runs on the Control Plane's Temporal worker; long-running ingestion runs on Knowledge Flow's.

Conversation flow

  1. The user authenticates through OIDC (Keycloak); the UI calls the Control Plane's prepare-execution endpoint with its bearer token.
  2. The Control Plane resolves the managed agent and returns an ingress-relative execution URL. No signed grant or capability token is issued — the control plane issues none.
  3. The UI calls the agentic pod directly at that URL, presenting the same Keycloak bearer token. The pod authenticates the JWT and authorizes the request itself with a per-request ReBAC (OpenFGA) check on the caller's team_id — there is no callback to the Control Plane on this path.
  4. The agentic pod executes the agent (ReAct or Graph via fred-runtime), consulting governance and model-routing policies for the effective model and tool behavior.
  5. Output and reasoning traces stream back to the UI over SSE, directly from the pod; checkpoints and session history are persisted by the pod.

Processing flow

Governance is policy-first. Model, tool/MCP, prompt, agent, and data-scope decisions are resolved from policies rather than hardcoded, and access is enforced by ReBAC (OpenFGA). See Policy-based LLM routing and Security.

Why this shape

Kubernetes deployment topology

A Fred instance runs entirely inside a single Kubernetes namespace. All external traffic enters through one Ingress. Agent execution pods — both the bundled fred-agents service and any custom team pods — are treated identically by the control plane and by the Ingress routing rules.

KUBERNETES CLUSTER fred namespace Kubernetes Ingress / → frontend /control-plane/ → cp-backend /knowledge-flow/ → kf-backend /runtime/{id}/ → agent pods User browser frontend React SPA agent catalog · chat UI session management apps/frontend control-plane-backend teams · agent instances sessions · prompts prepare-execution URLs · CP Temporal worker knowledge-flow-backend document ingestion · 31 formats 3 processing profiles vector retrieval (RAG) · KF Temporal worker · Agentic worker AGENT RUNTIME LAYER — isolated execution · Keycloak JWT + OpenFGA authorized per request fred-agents bundled general · rag · sql · sentinel test harness · OpenAI compat fred-runtime · fred-sdk LangGraph · MCP client · HITL apps/fred-agents libs/fred-runtime · libs/fred-sdk custom-agent-pod team-provided any agent logic · any tools any model provider fred-runtime · fred-sdk pip install fred-runtime fred-sdk deploy as standard container register in runtime_catalog_sources + N pods any registry any namespace identical routing INFRASTRUCTURE PostgreSQL state · sessions history OpenFGA ReBAC · tuples authorization Keycloak OIDC · PKCE identity OpenSearch vector index RAG retrieval MinIO / S3 object storage documents Temporal ingestion jobs background tasks LLM APIs OpenAI · Azure Ollama · … external
Reading the diagram. All traffic enters through the Kubernetes Ingress — there is no other exposed port. When a user starts an agent session, the frontend first calls the control plane's prepare-execution endpoint, which resolves the managed agent and returns an ingress-relative execution URL. There is no signed grant or capability token — the control plane issues none. The frontend then opens an SSE stream directly to the agent pod at /runtime/{id}/agents/execute/stream, presenting the user's own Keycloak bearer token. The agent pod authenticates that JWT and authorizes the request itself with a per-request ReBAC (OpenFGA) check on the caller's team — without calling back to the control plane. This design was chosen deliberately: an earlier revision had the control plane mint a signed ExecutionGrant, which was withdrawn because it made the control plane a proprietary cryptographic root of trust — an unnecessary homologation burden for a C3 deployment. Identity and authorization now rest entirely on Keycloak and OpenFGA, the same model already used elsewhere in the platform. The same flow applies to both the bundled fred-agents service and any custom agent pods. Agent pods are the only services that call external LLM APIs.

The agentic pod extensibility model

Any team can build and deploy their own agent pod by importing fred-runtime and fred-sdk. Once the pod is deployed and its base_url + runtime_id are added to control-plane-backend's runtime_catalog_sources, the control plane enrolls it and the Ingress gains a new /runtime/{runtime_id}/ route. From the user's perspective, a custom agent pod is indistinguishable from the bundled ones.

Future: FRDC v1 (proposed) will replace the static catalog with Kubernetes-native auto-discovery using Service labels (fred.io/runtime=true). Not yet implemented — the static runtime_catalog_sources list is the current production mechanism.

GKE on S3NS — network security model

The Fred instance runs on a private GKE cluster inside an S3NS tenant with no internet exposure. Cloud Armor (GCP-native WAF) enforces a strict separation between user traffic and admin traffic at the application layer, backed by source-IP allowlisting. All admin actions are captured in immutable Cloud Audit Logs — including every Cloud Console operation, with no SSH or VM involved.

S3NS PRIVATE CONNECTIVITY no internet exposure User CIDR employees · standard access any authenticated S3NS source Admin CIDR ops team · restricted range strict allowlist enforced Cloud Console HTTPS only · no SSH · no VMs GKE control plane API (private) External IdP corporate SSO · SAML · OIDC AD / LDAP federation GKE ON S3NS — PRIVATE CLUSTER CLOUD ARMOR — GCP-native WAF Policy: users allow authenticated · standard rate limits Policy: admin source IP: admin CIDR only all other sources → blocked GKE Control Plane API private endpoint HTTPS only · no SSH surface all actions → Cloud Audit Logs GKE Gateway API — Internal Load Balancer /* → user services /admin/* · /auth/admin/* → admin services User-facing services frontend (React SPA) control-plane-backend (user API) fred-agents (runtime · SSE) Keycloak OIDC (login · token) paths: / /control-plane/ /runtime/{id}/ Cloud Armor policy: users Admin-only services Keycloak admin console Object storage admin console control-plane admin endpoints paths: /auth/admin/ /storage/ /cp/admin/ admin CIDR only · others → HTTP 403 Cloud Armor policy: admin LLM API endpoint private · no internet egress via private connectivity Keycloak — IdP bridge OIDC · SAML · token issuance · PKCE federates to external identity provider → INFRASTRUCTURE PostgreSQL state · sessions OpenFGA ReBAC · authz OpenSearch vector index Cloud Storage objects · documents Temporal ingestion jobs Keycloak (data) identities · sessions AUDIT & NON-REPUDIATION Cloud Audit Logs all API calls · user · action · time incl. Cloud Console actions VPC Flow Logs network-level tracing per-CIDR visibility Log Bucket (WORM) locked · non-repudiable retention enforced · cannot be deleted Export path Log Bucket → Pub/Sub future: SIEM · SOC integration
Why no bastion, no custom WAF. There are no VMs and no SSH surface — a bastion protects nothing. Cloud Armor is the GCP-native WAF provided by S3NS; bringing a separate appliance would add complexity without adding protection. The admin CIDR allowlist in Cloud Armor provides structural separation: admin paths are unreachable from the user network at the L7 layer, independently of any application-level RBAC. Every Cloud Console action (RBAC changes, config updates, pod restarts) lands in Cloud Audit Logs automatically — no custom instrumentation required.