Unclassified

MCP + ADK + Spine Cache — Universal Communication Architecture

Tier C — Historical. This document is a point-in-time snapshot preserved for reference. For current architecture, see CANONICAL_PLATFORM_ARCHITECTURE.md.

Executive Summary

IntegrateWise provides three distinct connectivity paths all converging on the Spine (Cloudflare D1 + KV + R2 + Vectorize), enabling universal agent-to-agent communication regardless of runtime location or protocol:

  1. Connector Path — External tools (HubSpot, Jira, Slack, etc.) through standardized Loader/Normalizer/Spine ingestion
  2. MCP-to-MCP Path — Direct protocol communication between MCP-capable systems (AI clients, agents, tools)
  3. ADK Agent Path — Agent-to-agent communication via shared Spine Cache + Registry + Log Table

All three paths enforce the same governance principles: truth in the Spine, proposals before execution, audit everywhere.


Architecture Overview

┌─────────────────────────────────────────────────────────────────────────┐
│                         CONNECTIVITY LAYER                              │
├──────────────────────────┬──────────────────────┬─────────────────────────┤
│  Connector Path          │  MCP-to-MCP Path     │  ADK Agent Path         │
│  (External Tools)        │  (Direct Protocol)   │  (Spine-based Comms)    │
├──────────────────────────┼──────────────────────┼─────────────────────────┤
│ • HubSpot (Nango)        │ • Notion (native MCP)│ • Notion Agent          │
│ • Jira (Nango)           │ • Claude (MCP client)│ • Cloudflare Agent      │
│ • Slack (Nango)          │ • ChatGPT (MCP)      │ • Hostinger Agent       │
│ • Coda, Mintlify, etc.   │ • Direct MCP calls   │ • Custom agents (ADK)   │
│ • 26+ providers          │   (no transform)     │ • Any runtime + MCP     │
└────────┬─────────────────┴──────────┬───────────┴────────────┬───────────┘
         │                           │                        │
         │ Loader                    │ MCP Protocol           │ Spine Cache
         ↓ Normalizer               ↓ (register in           ↓ Registry (D1)
         │ Spine Write              │  Registry)             │ Log Table (D1)
         │                          │                        │
         └──────────────┬───────────┴────────────┬───────────┘
                        ▼
            ┌────────────────────────────────────┐
            │         SPINE (Universal Truth)     │
            ├────────────────────────────────────┤
            │ D1: Canonical entities, audit logs │
            │ KV: Spine Cache (shared context)   │
            │ KV: SIGNAL_CACHE, METRICS          │
            │ R2: Raw events, artifacts          │
            │ Vectorize: Semantic search index   │
            └────────────────────────────────────┘
                        │
         ┌──────────────┼──────────────┐
         │              │              │
         ▼              ▼              ▼
    Entity 360      Memory Hydration  ADK Agent Comms
    (Entity views)  (conversational,  (agent-to-agent
                     org, personal)    message passing)

Path 1: Connector Path (Nango + API Wrappers)

Flow

External Tool → Nango Connector (OAuth) → API Wrapper → Loader
    ↓
Normalizer (8-stage LLM pipeline)
    ↓ Strip tool-specific schema
    ↓ Map to canonical business entities
    ↓
Entity Resolution (dedup, merge, link)
    ↓
Spine Writer (D1 + R2 lineage + KV cache update)
    ↓
Spine (canonical truth for that entity)

Guarantee: "No Bypass"

  • ALL connectors (Nango providers AND custom API wrappers) MUST route through Loader/Normalizer/Spine
  • Direct writes to Spine bypassing normalization are strictly forbidden
  • Example: HubSpot deal → normalized to "Opportunity" entity with source lineage preserved

Supported Connectors (26+ providers via Nango)

ProviderTypeStatus
HubSpotNango✓ Active
JiraNango✓ Active
SlackNango✓ Active
CodaNango✓ Active
MintlifyNango✓ Active
SalesforceNango✓ Active
NotionNango + MCP✓ Active (dual support)
LinearNango✓ Active
GitHubNango✓ Active
AsanaNango✓ Active
Monday.comNango✓ Active
StripeAPI Wrapper✓ Active
AirtableAPI Wrapper✓ Active
[21+ others]Mixed✓ Active

Normalization Pipeline (8 stages)

Stage 1: Parse       — Extract raw event schema
Stage 2: Validate    — Check against provider signature
Stage 3: Transform   — Apply provider-specific mappings
Stage 4: Denormalize — Convert to canonical schema
Stage 5: Enrich      — Add computed fields, infer relationships
Stage 6: Validate    — Verify canonical schema compliance
Stage 7: Dedup       — Check for duplicates in Spine
Stage 8: Promote     — Write to D1 with full lineage

Lineage Tracking

Every entity preserves its origin:

{
  "entity_id": "opp_abc123",
  "entity_type": "Opportunity",
  "canonical_value": { "name": "Acme Deal", "value": 50000 },
  "source": {
    "provider": "hubspot",
    "event_id": "deal_xyz789",
    "connection_id": "conn_hubspot_1",
    "timestamp": "2026-06-19T14:30:00Z",
    "raw_payload_ref": "s3://bucket/raw/hubspot/deal_xyz789.json"
  }
}

Path 2: MCP-to-MCP Path (Direct Protocol Communication)

What is MCP?

Model Context Protocol — Standard protocol for AI systems and tools to communicate structured data and function calls.

  • Standardized by Anthropic (open standard)
  • Supported by: Claude, ChatGPT (native), Notion, custom integrations
  • Enables: structured tool discovery, typed schemas, async function calls

MCP Endpoint in IntegrateWise

Deployed endpoint: https://mcp.integratewise.ai (live June 9, 2026)

Authentication: OAuth 2.0 RS256 JWT (scope-bound)

18 Exposed Tools:

Tool GroupToolsAccess Level
kb.*kb.search, kb.list, kb.get_contextRead-only
memory.*memory.propose, memory.list, memory.getPropose-only (write restricted)
spine.*spine.query, spine.entity_360, spine.timelineRead-only
signal.*signal.emit, signal.list, signal.correlatePropose-only
proposal.*proposal.create, proposal.list, proposal.get_statusPropose-only (handoff)
search.*search.semantic, search.fulltext, search.entityRead-only

MCP Communication Flow

AI Client (Notion / Claude)
    │
    ├─ Discover MCP tools at mcp.integratewise.ai
    ├─ Authenticate with OAuth JWT
    └─ Call tool (e.g., kb.search)
         │
         ▼
    IntegrateWise MCP-CONNECTOR Worker
         │
         ├─ Verify scope (e.g., "kb:read")
         ├─ Authorize based on tenant + principal
         └─ Delegate to backend service
              │
              ├─ kb.search → KNOWLEDGE service (Vectorize semantic search)
              ├─ memory.propose → CONTINUITY service (memory write)
              ├─ spine.query → D1 query (authorized subset)
              └─ [... route to appropriate service ...]
              │
              ▼
    Return typed response to AI client
         │
         └─ MCP-CONNECTOR logs call to Spine Log Table (comms audit)

Key Property: Direct MCP-to-MCP Calls Bypass Normalizer

When both endpoints support MCP natively:

  • ✅ No Loader/Normalizer transformation overhead
  • ✅ Direct protocol call (preserves fidelity)
  • ✅ Still logged in Spine Log Table (for audit + replay)
  • ✅ Still enforces authentication (OAuth JWT)
  • ✅ Still registered in agent Registry (for discovery)

Example: Notion Agent calling Claude via MCP

Notion Agent
    ├─ Reads Spine Cache (agent registry)
    ├─ Discovers: "Claude endpoint available, MCP-capable"
    └─ Direct MCP call → Claude
         │ (no Loader/Normalizer)
         │
         └─ Claude responds with structured tool result
              │
              └─ Notion Agent writes outcome to Spine Cache + Log

Path 3: ADK Agent Communication (via Spine)

What is ADK?

Agent Development Kit — Framework for building, deploying, and scaling multi-agent systems on Cloudflare Durable Objects.

Core components:

  • Agent Registry (D1 table mapping agents to capabilities)
  • Spine Cache (KV shared context for agent communication)
  • Log Table (D1 communication history for sequencing + replay)
  • Agent Runtime (Cloudflare DO-based agent runtime with memory + tools + policies)

Agent-to-Agent Communication Substrate

Three agents (Notion, Cloudflare, Hostinger) can coordinate via Spine:

Agent A (Notion)
    │
    ├─ Read Spine Cache (shared state)
    ├─ Query Registry: "Who handles coda_write?"
    ├─ Discover: "Cloudflare Agent (id: agent_cf_1) handles coda_write"
    │
    ├─ Write to Spine Cache: {"request_id": "req_123", "type": "coda_write", "target": "agent_cf_1"}
    ├─ Write to Log Table: {sender_id, receiver_id, message_type, payload_ref, status: "pending"}
    │
    └─ Poll Log Table or subscribe to changes
         │
         ▼
Agent B (Cloudflare)
    │
    ├─ Monitor Spine Cache (watch pattern)
    ├─ Detect: "New coda_write request in cache"
    │
    ├─ Read full request from Spine Cache
    ├─ Process (execute coda_write action)
    │
    ├─ Write result to Spine Cache: {"request_id": "req_123", "result": {...}, "status": "completed"}
    ├─ Update Log Table: {status: "completed", result_ref}
    │
    └─ Notify Agent A (via cache watcher subscription)
         │
         ▼
Agent A receives result from Spine Cache

Spine Cache (KV): Shared Operational Context

What it stores:

  • Agent state snapshots
  • In-flight request state
  • Shared signals and metrics
  • Capability registrations

TTL: Configurable per use case (default: 24 hours)

Schema:

// Key pattern: agent:{agent_id}:state
{
  "agent:notion_1:state": {
    "status": "idle",
    "last_heartbeat": "2026-06-19T14:35:00Z",
    "capabilities": ["notion_read", "memory_propose"],
    "current_task": null
  },
  
  // Key pattern: request:{request_id}
  "request:req_123": {
    "sender_id": "agent_notion_1",
    "receiver_id": "agent_cf_1",
    "type": "coda_write",
    "payload": { "page_id": "...", "content": "..." },
    "status": "pending",
    "created_at": "2026-06-19T14:30:00Z",
    "result": null
  }
}

Registry (D1): Agent Routing Table

Table: agent_registry

{
  agent_id: "agent_cf_1",
  agent_name: "Cloudflare Intelligence Agent",
  runtime: "cloudflare_do",
  capabilities: ["coda_write", "hubspot_update", "memory_propose"],
  endpoint: "https://cf-agent.integratewise.ai/invoke",
  status: "active",
  tenant_id: "tenant_acme",
  updated_at: "2026-06-19T14:35:00Z",
  health_check_interval: 60,
  last_health_check: "2026-06-19T14:34:00Z"
}

Query patterns:

-- Agent discovery: find all agents handling "coda_write"
SELECT * FROM agent_registry 
WHERE tenant_id = ? 
  AND capabilities @> '["coda_write"]' 
  AND status = 'active'

-- Agent health: mark offline
UPDATE agent_registry 
SET status = 'offline' 
WHERE agent_id = ? AND last_health_check < NOW() - INTERVAL 2 MINUTE

-- Agent capability lookup
SELECT capabilities FROM agent_registry 
WHERE agent_id = ? AND tenant_id = ?

Log Table (D1): Communication History

Table: agent_communication_log

{
  log_id: "log_abc123",
  sender_agent_id: "agent_notion_1",
  receiver_agent_id: "agent_cf_1",
  message_type: "coda_write",
  request_id: "req_123",
  payload_ref: "s3://bucket/comms/req_123.json",
  status: "completed",  // pending | completed | failed | timeout
  result_status: "success",
  tenant_id: "tenant_acme",
  created_at: "2026-06-19T14:30:00Z",
  completed_at: "2026-06-19T14:30:15Z",
  duration_ms: 150,
  error_message: null,
  audit_id: "audit_xyz789"
}

Guarantees:

  • ✓ Every agent-to-agent message is logged
  • ✓ Enables replay and debugging
  • ✓ Enables sequencing for eventual consistency
  • ✓ Enables SLA tracking (duration_ms)

Communication Patterns

1. Synchronous (Request-Response via Log Table)

Agent A: Write request to Log Table → status: "pending"
Agent A: Poll Log Table for completion
Agent B: Read log entry, process request
Agent B: Update Log Table → status: "completed", result
Agent A: Read updated log entry, get result

Latency: <500ms for local agents, <5s for distributed agents

2. Asynchronous (Fire-and-Forget via Spine Cache)

Agent A: Write signal to Spine Cache
Agent A: Return immediately (no waiting)
Agent B: Subscribe to Spine Cache pattern
Agent B: Receive signal, process
Agent B: Update Spine Cache with result (Agent A can check later)

Use case: Non-critical signals, batch processing

3. Pub/Sub (Broadcast via Spine Cache)

Agent A: Publish signal to Spine Cache pattern: "signals:*"
Agent B, C, D: Subscribe to "signals:*"
All agents: Receive signal simultaneously
Each agent: Process independently, write result to own state

Use case: System-wide signals, multi-agent coordination


MCP Layer Deep Dive

Endpoint Architecture

External AI Client (Claude, ChatGPT, Notion)
    │
    └─ Connect to mcp.integratewise.ai
         │
         ├─ WebSocket (real-time streaming) OR
         └─ HTTP/SSE (request-response)
              │
              ▼
         MCP-CONNECTOR Worker (Cloudflare)
              │
              ├─ Parse MCP message
              ├─ Extract tool call (kb.search, memory.propose, etc.)
              ├─ Verify OAuth JWT token
              ├─ Check tenant + scopes (authorization)
              │
              ├─ Route to appropriate backend service
              │  ├─ kb.search → KNOWLEDGE (Vectorize semantic)
              │  ├─ memory.propose → CONTINUITY (write to memory)
              │  ├─ spine.query → D1 direct query
              │  ├─ signal.emit → INTELLIGENCE (signal processing)
              │  ├─ proposal.* → GOVERN (approval gate)
              │  └─ search.* → KNOWLEDGE (hybrid search)
              │
              ├─ Collect response
              ├─ Log to Spine Log Table (for audit)
              └─ Return MCP-formatted response
                   │
                   └─ Back to AI Client

Tool Categories

Read-Only Tools (kb., spine., search.*)

  • No side effects
  • Can be called freely (within rate limits)
  • Example: kb.search("How do we handle SaaS pricing?") → returns context

Propose-Only Tools (memory., signal., proposal.*)

  • Write side effects but non-executable
  • Create artifacts in Spine (memory records, signals, proposals)
  • Require human-in-loop for execution
  • Example: memory.propose({"type": "decision", "content": "..."})

Governance-Gated Tools (proposal.create via handoff)

  • Require approval before execution
  • Never execute directly; handoff to customer infrastructure
  • Example: proposal.create({"action": "update_hubspot_deal"}) → returns approval_url

ADK Layer Deep Dive

Agent Builder Framework

// ADK Agent definition
class MyAgent extends ADKAgent {
  capabilities = ["notion_read", "memory_propose", "signal_emit"]
  
  async initialize(context: AgentContext) {
    this.registry = context.registry
    this.spine_cache = context.spine_cache
    this.memory = context.memory
  }
  
  async execute(request: AgentRequest) {
    // Read shared context from Spine Cache
    const sharedState = await this.spine_cache.get("shared:state")
    
    // Discover other agents
    const agents = await this.registry.query({
      tenant_id: this.tenant_id,
      capabilities: ["coda_write"]
    })
    
    // Invoke another agent via Log Table + Spine Cache
    const result = await this.invoke_agent(agents[0].agent_id, {
      type: "coda_write",
      payload: { ... }
    })
    
    // Propose memory (no execution)
    await this.memory.propose({
      type: "decision",
      content: "Selected Cloudflare agent for coda_write"
    })
    
    // Return proposal (never execute directly)
    return {
      action: "...",
      explanation: "...",
      confidence: 0.87
    }
  }
}

ADK Runtime (Cloudflare DO)

Lifecycle:

1. Initialization
   - Agent reads Registry (discover peers)
   - Agent reads Spine Cache (load shared state)
   - Agent registers itself in Registry

2. Idle Loop
   - Poll Log Table for new messages
   - Monitor Spine Cache for signals
   - Health check peer agents (mark offline if no heartbeat)

3. Request Processing
   - Receive message from Log Table or Spine Cache
   - Execute agent logic (propose, don't execute)
   - Write result back to Log Table / Spine Cache

4. Shutdown
   - Unregister from Registry
   - Close Spine Cache subscriptions

Agent Policies

Before execution, agents evaluate policies:

Policy: "Cloudflare Agent can only invoke Notion Agent for read-only tasks"
Policy: "Memory proposals require confidence > 0.8"
Policy: "Signal emission limited to 100 per minute"
Policy: "Tenant isolation: agent_acme_1 can only access tenant_acme data"

Enforcement: Built into ADK runtime (fail-safe deny by default)


Governance & Execution Flow

The Hard Gate: "Propose, Don't Execute"

All three communication paths converge on governance before execution:

Agent Proposal
    │
    ├─ Routing through GOVERN worker
    │
    ├─ Evaluation:
    │  ├─ Risk score calculation
    │  ├─ Policy matching
    │  ├─ Scope validation
    │  └─ Tenant isolation check
    │
    ├─ Decision:
    │  ├─ Auto-approve (low-risk, policy match)
    │  ├─ HITL (human-in-the-loop required)
    │  └─ Reject (high-risk, policy violation)
    │
    └─ If approved:
         │
         └─ Handoff Layer
              │
              ├─ Package proposal in canonical contract
              ├─ Select target adapter (MCP, JSON, Zapier, etc.)
              └─ Dispatch to customer execution environment
                   │ (customer infrastructure, not IntegrateWise)
                   │
                   └─ Customer executes (they own execution)

Non-negotiable: No agent can bypass this gate. TenantBrainDO (per-tenant brain) enforces with 15-min alarm timeout.


Scalability & Performance

Spine Cache Performance

OperationLatencyScale
Cache read (KV)<10ms100K+ requests/sec
Cache write (KV)<10ms100K+ requests/sec
Registry query (D1)<50msmillions of agents
Log table insert (D1)<20msmillions of messages
Semantic search (Vectorize)<100msbillions of embeddings

Agent Communication SLA

PatternP50 LatencyP99 LatencyNotes
Local agents (same CF region)<50ms<200msvia Spine Cache
Distributed agents (cross-region)<500ms<2svia Log Table + polling
MCP direct call<100ms<500msno normalizer overhead
Connector path (with normalizer)<2s<10s8-stage pipeline

Security & Multi-Tenancy

Tenant Isolation

Every query includes tenant_id scoping:

// Registry lookup (tenant-scoped)
SELECT * FROM agent_registry 
WHERE tenant_id = ? AND agent_id = ?

// Cache key (tenant-scoped)
Key: "{tenant_id}:agent:{agent_id}:state"

// Log table (tenant-scoped)
SELECT * FROM agent_communication_log 
WHERE tenant_id = ? AND created_at > ?

// Memory access (RLS in Supabase)
SELECT * FROM org_memory 
WHERE tenant_id = ? AND org_id = ? -- RLS enforces

Authentication & Authorization

OAuth 2.0 RS256 JWT on all MCP calls:

Token payload:
{
  "sub": "user_abc123",
  "aud": "mcp.integratewise.ai",
  "scope": ["kb:read", "memory:propose"],
  "tenant_id": "tenant_acme",
  "iat": 1718819400,
  "exp": 1718823000
}

Scope binding:

  • kb:read — Can call kb.search, kb.list, kb.get_context
  • memory:propose — Can call memory.propose (write to memory)
  • spine:read — Can call spine.query (subset of entities)
  • signal:emit — Can call signal.emit (emit signals)

Audit Trail

100% cloud-based logging (no local agent state):

1. Agent communication logged to Log Table (D1)
2. All MCP calls logged to MCP audit trail
3. All governance decisions logged with reasoning
4. All memory writes logged with source + principal
5. Retention: 2 years (compliant with SOC2)

Deployment & Operations

Environments

EnvironmentAgentsSpineMCPGovernance
devLocal + CloudflareD1 dev DBlocalhost MCPAuto-approve
testCloudflare stagingD1 test DBtest.mcp.integratewise.aiHITL simulated
prodCloudflare prodD1 prod DBmcp.integratewise.aiHITL real

Monitoring & Observability

Metrics tracked:

Agent metrics:
- Registry query latency (p50, p99)
- Spine Cache hit rate (%)
- Log table write latency (p50, p99)
- Agent health (active/offline/error)
- Communication success rate (%)

MCP metrics:
- Tool call latency per tool (ms)
- Authentication failures (count)
- Scope violations (count)
- Rate limit hits (count)

Governance metrics:
- Proposal approval rate (%)
- Average approval time (minutes)
- Policy violations (count)
- Execution success rate (%)

Example: Multi-Agent Workflow

Scenario: "Automatically update HubSpot based on Coda document changes"

Agents involved:

  1. Notion Agent (reads document changes)
  2. Cloudflare Agent (handles HubSpot integration)
  3. Hostinger Agent (executes on customer infrastructure)

Flow:

1. Notion Agent
   ├─ Receives webhook: Coda document updated
   ├─ Reads Spine Cache for current opportunities
   ├─ Queries Registry: "Who handles hubspot_update?"
   └─ Discovers: Cloudflare Agent (agent_cf_1)

2. Notion Agent → Cloudflare Agent (via Log Table)
   ├─ Write to Log Table: {type: "hubspot_update", target_id: "opp_123", data: {...}}
   ├─ Poll Log Table for completion

3. Cloudflare Agent
   ├─ Monitor Log Table (watch pattern for messages to agent_cf_1)
   ├─ Read message from Log Table
   ├─ Prepare HubSpot API call
   ├─ Create PROPOSAL (not execute yet)
   └─ Write to Spine Cache: {request_id, proposal, status: "pending_approval"}

4. Governance Gate (GOVERN worker)
   ├─ Evaluate proposal
   ├─ Decision: HITL (needs human approval)
   └─ Return approval_url

5. Human in L7 Approval Center
   ├─ Review proposal with evidence
   ├─ Click "Approve"
   └─ Governance marks as approved

6. Handoff Layer
   ├─ Package approved proposal in canonical contract
   ├─ Select adapter: MCP (Hostinger supports MCP)
   └─ Dispatch to Hostinger Agent

7. Hostinger Agent (customer infrastructure)
   ├─ Receive handoff package
   ├─ Execute HubSpot API call (in their environment)
   ├─ Capture outcome
   └─ Send outcome back to IntegrateWise

8. Outcome Ingestion (Return Loop)
   ├─ Receive: {status: "success", hubspot_id: "deal_456"}
   ├─ Update Spine: Mark opportunity as synchronized
   ├─ Update Memory: Log successful action
   ├─ Update Graph: Record entity relationship
   └─ Notify all agents via Spine Cache (broadcast signal)

9. All agents
   ├─ Subscribe to Spine Cache for outcome signal
   ├─ Read final state from Spine
   ├─ Update their models based on new ground truth
   └─ Ready for next workflow

Result: Universal agent coordination with no vendor lock-in, full governance, complete audit trail.


Key Invariants (MCP + ADK + Spine Cache)

  1. One Spine, Many Agents — All agents share same D1 source of truth
  2. Registry is the Discovery Mechanism — Agents find each other via Registry, not hardcoded
  3. Log Table is the Communication Bus — Every agent-to-agent message recorded for audit + replay
  4. Spine Cache is Shared State — Agents read/write operational state, not private memory
  5. No Bypass, No Exception — All proposals flow through governance gate (fail-safe deny)
  6. Tenant Isolation on Every Query — Every D1/KV access scoped by tenant_id (no data leakage)
  7. Audit Everything — All MCP calls, registry lookups, cache reads/writes logged
  8. Eventual Consistency — Agent state converges through polling Log Table + Spine Cache subscriptions

Conclusion

MCP + ADK + Spine Cache together enable:

✓ Universal Communication — Any agent (Notion, Cloudflare, Hostinger, custom) can communicate with any other
✓ Zero Vendor Lock-in — Standard protocols (MCP, OAuth) + Spine as neutral ground truth
✓ Full Governance — All execution gated through HITL approval before reaching customer infrastructure
✓ Complete Observability — 100% audit trail (no local agent state, everything in cloud)
✓ Scalable Architecture — Millions of agents, billions of messages, no single point of failure

The Spine is the universal substrate. MCP + ADK are the connective tissues. Governance is the hard gate. Together, they enable an open, auditable, secure multi-agent operating system.