Skip to content

Architecture Overview

System Architecture (v0.3.0)

SCP uses a graph-based dynamic context selection model with two distinct paths:

┌─────────────────────────────────────────────────────────────────────────┐
│                         INGESTION PATH                                   │
│                                                                          │
│  Versioned Bundle ──► Bundle Registry ──► Graph Database                │
│                           (API)           (relationships)                │
│                             │                                            │
│                             ▼                                            │
│                      Rules Engine ──────► Graph Database                │
│                      (formularies)        (operational edges)            │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                         RUNTIME PATH                                     │
│                                                                          │
│  Agent Request ──► Auth ──► Intent Check ──► Graph Query ──► Stream    │
│       │             │            │               │              │        │
│       │             │            │               │              ▼        │
│   API Key      Agent Registry  Allowed      Role-based      Context     │
│               (identity/role)  Intents      Traversal       Delivery    │
└─────────────────────────────────────────────────────────────────────────┘

Services

Service Port(s) Purpose Technology
Control Plane API 8000 Bundle Registry, Agent Registry, REST context API FastAPI
Context Service 8002 (gRPC), 8003 (webhook) Real-time streaming, tag subscriptions gRPC, aiohttp
Rules Engine 8001 Custom business rules (formularies, networks) FastAPI
Telemetry Service 8004 Usage reporting FastAPI
Graph Database 5432 Relationship storage, Cypher queries PostgreSQL + Apache AGE
Redis 6379 Pub/sub for real-time updates Redis
Caddy 443, 8443 TLS termination, reverse proxy Caddy

Technology Stack

  • Backend: FastAPI (async Python), gRPC (asyncio)
  • Database: PostgreSQL with Apache AGE extension (graph + relational)
  • Pub/Sub: Redis (for context update broadcasting)
  • Connection Pooling: asyncpg
  • Type Safety: Pydantic, Protocol Buffers
  • Servers: Uvicorn (ASGI), gRPC server

Core Concepts

The Control Hierarchy

Global context (bundles/graph) ──► applies to all agents
         │
         ▼
Role-based context (role nodes) ──► applies to all agents with this role
         │
         ▼
Agent-specific context (overrides) ──► applies to ONE agent

Key Insight: Separation of Authoring from Selection

  • Bundles define the world (stable, generic, reusable)
  • Graph indexes the world (relationships, traversable)
  • Context Service enforces the rules (policy gating)
  • Agents operate inside the slice they're given

Graph Database

Why Graph?

  1. Relationships already exist - Bundles have structural relationships (imports, references, applies_to). Graph surfaces these in queryable form.

  2. Dynamic selection without manual mapping - No need for explicit role → context mappings. Graph traverses relationships based on request.

  3. Agent-level control - Can adjust context for individual misbehaving agents without code changes.

  4. Simpler context authoring - Authors create well-connected content. Graph figures out what's relevant at runtime.

Graph Schema

Nodes: - Bundle - Versioned context packages - SCD - Structured Context Documents - Role - Agent roles (prior-auth-agent, claims-processor) - Agent - Individual agent instances

Edges (from bundles): - CONTAINS - Bundle contains SCDs - IMPORTS - Bundle imports another bundle - APPLIES_TO - SCD applies to role - GOVERNED_BY - SCD governed by another SCD - REFERENCES - SCD references another SCD

Edges (from rules DB): - ON_FORMULARY - Drug on formulary - IN_NETWORK - Provider in network - REQUIRES_PRIOR_AUTH - Service requires PA

Edges (from agent registry): - HAS_ROLE - Agent has role - HAS_OVERRIDE - Agent has SCD override - HAS_RESTRICTION - Agent has SCD restriction

Example Cypher Queries

Get all SCDs for a role:

MATCH (s:SCD)-[:APPLIES_TO]->(r:Role {id: 'role:prior-auth-agent'})
RETURN s.id, properties(s)

Get SCDs with governance chain:

MATCH (s:SCD)-[:APPLIES_TO]->(r:Role {id: 'role:prior-auth-agent'})
OPTIONAL MATCH (s)-[:GOVERNED_BY]->(g:SCD)
OPTIONAL MATCH (s)-[:REFERENCES]->(ref:SCD)
RETURN s.id, collect(DISTINCT g.id), collect(DISTINCT ref.id)


Agent Registry

Agent Registration Model

Agents are registered with: - Identity - Unique agent ID - Role - What role this agent has (determines base context) - Allowed Intents - What task types this agent can request context for - API Key - Authentication credential

The Thin Client Model

The agent becomes a thin client: - Minimal baked-in knowledge - Gets context from SCP at runtime - Can be controlled/adjusted via the control plane

# Agent registration example
{
    "agent_id": "agent:prior-auth-prod",
    "name": "Prior Auth Production Agent",
    "role_id": "role:prior-auth-agent",
    "allowed_intents": [
        "prior_auth_check",
        "formulary_lookup",
        "clinical_guidelines_check"
    ],
    "status": "active"
}

Policy Overrides

Individual agents can have: - Overrides - Additional SCDs beyond their role's default - Restrictions - SCDs to exclude from their context

# Agent with restrictions
{
    "agent_id": "agent:prior-auth-restricted",
    "role_id": "role:prior-auth-agent",
    "restrictions": ["scd:project:phi-handling"]  # This SCD will be excluded
}

Context Request Flow (v0.3)

1. Authentication

Agent sends request with API key:

POST /api/context
X-API-Key: sk_abc123...
Content-Type: application/json

{
    "task_type": "prior_auth_check",
    "params": {"drug": "Keytruda", "diagnosis": "lung cancer"}
}

2. Intent Validation

Orchestrator checks: - Is API key valid? - Is agent active? - Is prior_auth_check in agent's allowed_intents?

3. Graph Query

Based on agent's role, query graph for relevant SCDs:

MATCH (s:SCD)-[:APPLIES_TO]->(r:Role {id: 'role:prior-auth-agent'})
RETURN s.id

4. Policy Filtering

Apply agent-specific overrides/restrictions: - Add any override SCDs - Remove any restricted SCDs

5. Context Delivery

Return filtered SCDs to agent:

{
    "success": true,
    "agent_id": "agent:prior-auth-prod",
    "role_id": "role:prior-auth-agent",
    "task_type": "prior_auth_check",
    "scd_ids": [
        "scd:standards:hipaa-privacy-rule",
        "scd:project:clinical-guidelines-v1.2",
        "scd:project:formulary-2024"
    ],
    "scd_content": { ... },
    "processing_time_ms": 34
}

6. Audit Logging

Every request logged: - Agent ID, Role ID - Task type, Parameters - SCDs returned - Timestamp, Processing time


Bundle Hierarchy

The bundle system uses a hierarchical import model:

Meta Bundle (SCS Foundation)
  ↓ imports
Standards Bundles (External: HIPAA, SOC2, CHAI, NIST)
  ↓ imports
Domain Bundle (The Company - e.g., Acme Health Corp)
  ↓ imports multiple
Concern Bundles (Functional Areas: Architecture, Security, Clinical, Data)
  ↓ imported by
Project Bundles (Individual Initiatives: Prior Auth App, Patient Portal)

See Bundle Types Guide for detailed explanations.


Import Resolution

When a bundle is materialized to the graph, all imports are recursively resolved:

Input: bundle:prior-auth:1.0.0

Output (resolved dependency graph):

1. bundle:meta:1.0.0                 (Meta - foundation)
2. bundle:hipaa:1.0.0                (Standards)
3. bundle:chai:1.0.0                 (Standards)
4. bundle:soc2:1.0.0                 (Standards)
5. bundle:acme-architecture:1.0.0    (Concern)
6. bundle:acme-security:1.0.0        (Concern)
7. bundle:acme-clinical:1.0.0        (Concern)
8. bundle:acme-company-context:1.0.0 (Concern)
9. bundle:acme-health-corp:1.0.0     (Domain)
10. bundle:prior-auth:1.0.0          (Project)

All SCDs from all bundles are added as nodes with relationships preserved.


API Endpoints

Control Plane API (Port 8000)

Bundle Registry: - POST /api/bundles - Create/publish bundle - GET /api/bundles - List bundles - GET /api/bundles/{id}/versions/{v} - Get specific version - DELETE /api/bundles/{id}/versions/{v} - Deactivate bundle

Agent Registry: - POST /api/agents - Register agent - GET /api/agents - List agents - GET /api/agents/{id} - Get agent details - PUT /api/agents/{id} - Update agent - POST /api/agents/{id}/api-keys - Generate API key - DELETE /api/agents/{id}/api-keys/{key_id} - Revoke API key

Context (REST): - POST /api/context - Request context (v0.3 intent-based) - GET /api/context/health - Health check

Tags: - POST /api/tags - Create tag - PUT /api/tags/{tag} - Update tag - GET /api/tags/{tag} - Resolve tag

Context Service (Port 8002 gRPC, Port 8003 Webhook)

gRPC Methods: - Subscribe(tag, agent_id) - Subscribe to tag stream (v0.2) - RequestContext(api_key, task_type, params) - Request context (v0.3)

Webhook: - POST /webhook/tag-update - Receives tag update notifications

Rules Engine (Port 8001)

  • POST /api/rules/schemas - Create rule schema
  • POST /api/rules/rule-sets - Create rule set
  • POST /api/rules/rule-sets/{id}/rules - Add rule
  • GET /api/rules/rule-sets - List rule sets

Database Schema

Index/Ledger Database

Core Tables: - bundles - Bundle storage (id, version, type, manifest JSONB) - tags - Tag → bundle mappings - deployments - Multi-bundle deployments - events - Lifecycle audit trail

Agent Registry Tables: - agents - Agent registration (id, name, role_id, allowed_intents) - agent_api_keys - API keys (key_id, key_hash, agent_id) - agent_policy_overrides - Per-agent SCD overrides/restrictions - agent_context_requests - Audit log of all context requests

Graph Database (Apache AGE)

Graph Name: scp_context

Vertex Labels: - Bundle, SCD, Role, Agent

Edge Labels: - CONTAINS, IMPORTS, APPLIES_TO, GOVERNED_BY, REFERENCES - HAS_ROLE, HAS_OVERRIDE, HAS_RESTRICTION


v0.2 vs v0.3 Comparison

Aspect v0.2 (Tag-based) v0.3 (Intent-based)
Flow Subscribe to tag → get full bundle Request for task → get relevant subset
Selection Flatten entire bundle graph Graph traversal based on role
Streaming Continuous stream with updates Request/response (can also stream)
Filtering None (get everything) Role-based + agent-specific policy
Use Case Design-time (full context) Runtime (minimal governance context)

Both modes are supported. v0.2 Subscribe is ideal for dev agents that need full context. v0.3 RequestContext is ideal for production agents that need minimal governance context.


Security Model

Current Implementation

  • ✅ Agent API key authentication (per-agent, expiry, revocation, lifecycle enforcement)
  • ✅ Admin API key authentication (bundle management, agent registry, audit admin)
  • ✅ Intent validation (agents restricted to their registered allowed task types)
  • ✅ Role-based context access (different roles receive different SCDs)
  • ✅ Tamper-evident audit log (hash chain, immutability trigger, RLS)
  • ✅ TLS (Caddy reverse proxy, Postgres sslmode)
  • ✅ Secrets management (no insecure defaults, startup validation)
  • ✅ License key enforcement (RS256 JWT, agent cap)

Planned Enhancements

  • OAuth2/OIDC for admin console SSO
  • Multi-tenancy with organization isolation
  • Fine-grained RBAC for bundle management

Deployment Architecture

Docker Compose (Pilot / Self-Hosted)

Caddy (ports 443, 8443) — TLS termination
  │
  ├── API Server (port 8000, internal)
  ├── Context Service (ports 8002/8003, internal)
  ├── Rules Engine (port 8001, internal)
  ├── Telemetry Service (port 8004, internal)
  ├── PostgreSQL + Apache AGE (port 5432, internal)
  └── Redis (port 6379, internal)

AWS (Production)

ALB (TLS) → EC2 instance running Docker Compose
              ├── All services (internal Docker network)
              ├── Secrets from SSM Parameter Store
              └── Daily backups to S3

See AWS Setup Guide for the full CloudFormation deployment.