Skip to content

AgentOS — End-to-End Sequence Flow

Full Request Lifecycle

This document traces every request from the AI agent through to evidence recording, showing which OTel spans are emitted at each stage.

sequenceDiagram
    participant A as AI Agent
    participant E as AgentOS Edge<br/>:8443 TLS
    participant MW as Middleware Chain<br/>(Auth/RL/CORS)
    participant GW as Gateway Handler
    participant PI as Policy Engine<br/>(Input)
    participant RT as Router
    participant OAI as OpenAI / Provider
    participant PO as Policy Engine<br/>(Output)
    participant CR as Credential Broker
    participant AP as Approval Queue
    participant EV as Evidence Chain
    participant JS as Jaeger + TraceStore

    Note over A,E: PHASE 1 — Edge Layer (AgentOS Edge)
    A->>E: HTTPS/2 POST /api/v1/chat/completions
    activate E
    Note over E: [span: edge.request start]<br/>TLS 1.3 decrypt<br/>Check CPU% → adaptive load shed<br/>Token bucket rate limit<br/>Circuit breaker allow()?<br/>Select upstream: /api/* → :8080

    E->>MW: HTTP/2 (internal h2c)
    deactivate E

    Note over A,MW: PHASE 2 — Middleware Chain
    activate MW
    MW->>MW: Auth — extract API key → tenant
    MW->>MW: RateLimit — Allow(tenantID)?
    MW->>MW: CORS headers
    MW->>MW: BudgetCheck (model-level)
    MW->>MW: Logging + Prometheus counter
    MW->>GW: pass request
    deactivate MW

    Note over GW,PI: PHASE 3 — Gateway + Policy Input
    activate GW
    Note over GW: [span: gateway.chat_completion start]<br/>Behavioral kill-switch check<br/>Apply model aliases<br/>Apply transforms

    GW->>PI: CheckInput(messages)
    activate PI
    Note over PI: [span: policy.check_input]<br/>keyword → regex → PII → WASM<br/>Attr: decision, policy_name
    PI-->>GW: Violation (allow/block/warn)
    deactivate PI

    alt Violation == block
        GW-->>A: 403 policy_violation
        Note over GW: span ended with error
    end

    Note over GW,RT: PHASE 4 — Provider Call (most expensive stage)
    GW->>RT: RouteWithProvider(ctx, req)
    activate RT
    Note over RT: [span: provider.call]<br/>Select provider by model/strategy<br/>Check circuit breaker
    RT->>OAI: POST /v1/chat/completions
    activate OAI
    Note over OAI: [span: provider.openai]<br/>Attrs: tokens_prompt, tokens_completion<br/>Latency: typically 500ms–3000ms
    OAI-->>RT: ChatCompletionResponse
    deactivate OAI
    RT-->>GW: RoutedResponse{Response, Provider}
    deactivate RT

    Note over GW,PO: PHASE 5 — Policy Output
    GW->>PO: CheckOutput(response.choices[0].content)
    activate PO
    Note over PO: [span: policy.check_output]<br/>keyword → regex → WASM
    PO-->>GW: Violation (allow/block)
    deactivate PO

    Note over GW,EV: PHASE 6 — Evidence + Side Effects
    GW->>EV: Record(ActionEnvelope)
    activate EV
    Note over EV: [span: evidence.record]<br/>Attrs: hash, session_id<br/>SHA-256 chain append
    EV-->>GW: ok
    deactivate EV

    GW->>GW: Usage.Record(tenant, provider, model, tokens)
    GW->>GW: Analytics.Record(DataPoint)
    GW->>GW: AuditLog(event)

    GW-->>A: 200 ChatCompletionResponse
    Note over GW: [span: gateway.chat_completion end]<br/>Total duration recorded
    deactivate GW

    Note over GW,JS: PHASE 7 — Telemetry Export (async)
    GW--)JS: OTLP gRPC export (batched, ~5s)<br/>Spans: edge + gateway + policy×2 + provider + evidence
    JS--)JS: Jaeger UI shows full trace tree
    JS--)JS: TraceStore.Add(TraceSummary) → dashboard

MCP Tool Call Flow

sequenceDiagram
    participant A as AI Agent
    participant E as AgentOS Edge :8443
    participant MCP as MCP Gateway :9090
    participant TP as Tool Policy Engine
    participant AP as Approval Queue
    participant CR as Credential Broker
    participant Tool as Upstream Tool Server

    A->>E: POST /mcp/* (HTTP/2)
    E->>MCP: forward (circuit breaker checked)

    activate MCP
    Note over MCP: [span: mcpgw.tool_call]<br/>Parse MCP tool call envelope

    MCP->>TP: Check(protocol, tool, target, capability)
    TP-->>MCP: Decision: allow | review | block

    alt Decision == review
        MCP->>AP: Enqueue(ApprovalItem)
        Note over AP: [span: approval.enqueue]<br/>Notify GitHub/Slack<br/>Wait for human decision
        AP-->>MCP: approved / denied
    end

    alt Decision == allow
        Note over MCP: [span: credential.issue] (call-site wrapper)
        MCP->>CR: Issue(credentialRef)
        CR-->>MCP: Token (scoped, TTL-bound)
        MCP->>Tool: Execute with credential
        Tool-->>MCP: Result
    end

    MCP-->>A: MCP Response
    deactivate MCP

Span Inventory

Span Name Emitted By Key Attributes
edge.request edgeproxy/proxy.go http.method, http.url, upstream, status_code
gateway.chat_completion gateway/handler.go tenant_id, model, stream
policy.check_input gateway/handler.go (wrapper) decision, policy_name, action
provider.call gateway/handler.go (wrapper) provider, model, latency_ms
provider.openai gateway/handler.go (wrapper) tokens_prompt, tokens_completion, tokens_total
provider.anthropic gateway/handler.go (wrapper) same as openai
provider.ollama gateway/handler.go (wrapper) same as openai
policy.check_output gateway/handler.go (wrapper) decision
evidence.record gateway/handler.go (wrapper) hash, session_id
mcpgw.tool_call mcpgw (call-site) tool, target, capability, decision
approval.enqueue mcpgw (call-site) approval_id, tool, timeout
credential.issue mcpgw (call-site) credential_name, ttl, scope

Latency Budget (Typical)

edge.request              total: ~1350ms
├── edge overhead              5ms   (TLS + routing + metrics)
├── gateway.chat_completion  1345ms
│   ├── policy.check_input      3ms
│   ├── provider.call         1330ms
│   │   └── provider.openai   1330ms  ← usually 95%+ of total
│   ├── policy.check_output     4ms
│   └── evidence.record         2ms

P95 latency is dominated entirely by the upstream LLM provider.