Skip to content

Instantly share code, notes, and snippets.

@jordotech
Created July 22, 2026 14:26
Show Gist options
  • Select an option

  • Save jordotech/616d1ea548e0db9f0ecd0ab5d88f5bdb to your computer and use it in GitHub Desktop.

Select an option

Save jordotech/616d1ea548e0db9f0ecd0ab5d88f5bdb to your computer and use it in GitHub Desktop.
Capitol AI — External Chat (embed) request flow

Capitol AI — External Chat (Embed) Request Flow

The embeddable collection-chat widget: an agentic Claude loop that answers questions grounded in a collection's documents, streamed to the browser over SSE.

Services involved

Service Role
platform-frontend Embed widget UI (iframe) — renders SSE stream
platform-api POST /{orgid}/collections/{collection_id}/external-chat — auth, agentic loop, SSE
clj-pg-wrapper Resolves Auth0 embed user (/api/v1/users/ensure)
DynamoDB Embed API keys, collection config, chat history
Archestra MCP gateway (http://archestra:9000/v1/mcp/{gateway-id})
mcp-servers-runner unstructured-collections-server (cap-uc) MCP tools behind Archestra
qdrant-svc /search/hybrid vector + keyword retrieval
Anthropic API Claude — https://api.anthropic.com/v1/messages (streamed)

Not in this path: metamcp (mcp.capitol.ai) fronts mcp-servers-runner for the LibreChat / customer-chat feature, a separate flow. Embed external-chat routes through Archestra, not metamcp.

Sequence

sequenceDiagram
    autonumber
    participant B as Browser (embed iframe)<br/>platform-frontend
    participant API as platform-api<br/>external_chat.py
    participant CLJ as clj-pg-wrapper
    participant DDB as DynamoDB
    participant ARCH as Archestra<br/>MCP Gateway
    participant MSR as mcp-servers-runner<br/>(cap-uc / unstructured)
    participant QD as qdrant-svc
    participant AN as Anthropic API<br/>Claude

    B->>API: POST /{orgid}/collections/{cid}/external-chat<br/>(embed API key, message, conversation_id?)
    API->>DDB: validate embed API key
    API->>CLJ: ensure Auth0 embed user
    CLJ-->>API: user_id
    API->>DDB: load collection config
    API->>DDB: hydrate conversation history

    Note over API,AN: Agentic loop (streamed as SSE to browser)
    loop until Claude returns final answer (tool-round cap)
        API->>AN: stream messages + tool defs
        AN-->>API: tool_use: cap-uc search
        API->>ARCH: MCP call_tool (Bearer org token, organization_id arg)
        ARCH->>MSR: proxy to unstructured-collections-server
        MSR->>QD: /search/hybrid (custom_filters)
        QD-->>MSR: chunk matches
        MSR-->>ARCH: tool result
        ARCH-->>API: tool result
        API-->>B: SSE keepalive + partial tokens
    end

    AN-->>API: final assistant message
    API->>DDB: persist user + assistant messages
    API-->>B: SSE final answer + citations, [DONE]
Loading

Notes

  • Auth boundary: embed API key (per-collection) validated first; Auth0 user resolved via clj-pg-wrapper.
  • Tenant isolation: organization_id passed as an explicit MCP tool arg to close the Archestra passthrough cache leak (ENG-1335).
  • Long-conversation survival (ENG-3629): tool-round cap + SSE keepalive prevent gateway/read timeouts on long agentic loops.
  • Streaming: single httpx.AsyncClient reused across the loop; response streamed to the browser as SSE throughout, not just at the end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment