Skip to content

🔌 Traylinx Cortex Integration Guide

📚 Navigation: Main README | Docs Index | API Reference | Database Schema


This document outlines how Traylinx Cortex integrates with the wider Traylinx ecosystem, including authentication via Sentinel, discovery via Agent Registry, and communication via A2A protocols.


1. 🔐 Authentication (Traylinx Sentinel)

Cortex acts as both a Consumer (calling LLMs/SwitchAI) and a Provider (serving chat APIs to other agents/apps). It must be fully secured using Traylinx Sentinel.

A. Identity Setup

Cortex requires its own credentials in Sentinel: * Client ID: traylinx-cortex * Client Secret: (Managed via Environment Variable) * Agent User ID: (Unique UUID for Cortex)

B. Authentication Headers

All A2A requests to Cortex must include these headers:

Content-Type: application/vnd.traylinx.a2a+json; version=1
Authorization: Bearer {access_token}
X-Agent-Key: {agent_key}
X-Agent-Secret-Token: {agent_secret}
Header Description
Content-Type A2A protocol content type with version
Authorization Bearer token from Sentinel (OAuth2)
X-Agent-Key Your agent's unique identifier
X-Agent-Secret-Token Your agent's secret for additional verification

C. Protecting Endpoints (Provider Mode)

All Cortex A2A endpoints must be protected using the traylinx_auth_client SDK.

Python Example:

from traylinx_auth_client import require_a2a_auth
from fastapi import APIRouter, Request

router = APIRouter()

@router.post("/a2a/conversation/chat")
@require_a2a_auth  # <--- Enforces Sentinel Authentication
async def chat_endpoint(request: Request, payload: A2AChatRequest):
    # If we reach here, the request is authenticated
    # The calling agent's identity is available in request.state.agent
    agent_key = request.state.agent["agent_key"]
    return await cortex_manager.process(payload)

D. Making Requests (Consumer Mode)

When Cortex needs to call other internal agents (e.g., if it needs to delegate a task), it uses the SDK to sign requests.

Python Example:

from traylinx_auth_client import make_a2a_request

# Example: Cortex calling a specialized "Math Agent"
response = make_a2a_request(
    method="POST",
    url="http://math-agent:8080/a2a/calculate",
    json={
        "envelope": {
            "message_id": str(uuid.uuid4()),
            "sender_agent_key": "traylinx-cortex",
            "timestamp": datetime.utcnow().isoformat() + "Z"
        },
        "action": "calculate",
        "payload": {"expression": "2 + 2"}
    }
)


2. 📡 A2A Protocol Format

Request Envelope Structure

All A2A requests follow this standard envelope format:

{
  "envelope": {
    "message_id": "msg-uuid-001",
    "sender_agent_key": "calling-agent",
    "timestamp": "2025-11-27T10:00:00Z",
    "correlation_id": "optional-for-threading"
  },
  "action": "conversation.chat",
  "payload": {
    // Action-specific data
  }
}

Response Envelope Structure

{
  "envelope": {
    "message_id": "response-uuid-001",
    "correlation_id": "msg-uuid-001",
    "in_reply_to": "msg-uuid-001",
    "sender_agent_key": "traylinx-cortex",
    "timestamp": "2025-11-27T10:00:01Z"
  },
  "action": "conversation.chat",
  "payload": {
    // Response data
  }
}

Cortex A2A Actions

Action Endpoint Description
conversation.chat POST /a2a/conversation/chat Send message and get AI response
conversation.create POST /a2a/conversation/create Create new conversation session
conversation.history POST /a2a/conversation/history Get conversation history

3. 📬 A2A Endpoint Examples

3.1. Create Conversation (A2A)

Endpoint: POST /a2a/conversation/create

Request:

{
  "envelope": {
    "message_id": "msg-001",
    "sender_agent_key": "my-agent",
    "timestamp": "2025-11-27T10:00:00Z"
  },
  "action": "conversation.create",
  "payload": {
    "user_id": "user-123",
    "app_id": "my-app",
    "metadata": {
      "language": "en",
      "source": "agent"
    }
  }
}

Response (201 Created):

{
  "envelope": {
    "message_id": "response-001",
    "correlation_id": "msg-001",
    "in_reply_to": "msg-001",
    "sender_agent_key": "traylinx-cortex",
    "timestamp": "2025-11-27T10:00:01Z"
  },
  "action": "conversation.create",
  "payload": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "created_at": "2025-11-27T10:00:01Z"
  }
}

3.2. Chat (A2A)

Endpoint: POST /a2a/conversation/chat

Request:

{
  "envelope": {
    "message_id": "msg-002",
    "sender_agent_key": "my-agent",
    "timestamp": "2025-11-27T10:00:05Z"
  },
  "action": "conversation.chat",
  "payload": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "message": "I'm planning a trip to Tokyo. Can you help?",
    "user_id": "user-123",
    "config": {
      "stream": false,
      "model_preference": "balanced",
      "switch_ai_api_key": "sk-user-specific-key",
      "embedding_model": "mistral-embed"
    }
  }
}

Response (200 OK):

{
  "envelope": {
    "message_id": "response-002",
    "correlation_id": "msg-002",
    "in_reply_to": "msg-002",
    "sender_agent_key": "traylinx-cortex",
    "timestamp": "2025-11-27T10:00:07Z"
  },
  "action": "conversation.chat",
  "payload": {
    "message_id": "msg_abc123",
    "content": "Sure! Tokyo is amazing. What aspects of your trip would you like help with?",
    "usage": {
      "tokens_in": 50,
      "tokens_out": 25
    },
    "cost_usd": 0.000150
  }
}


4. 📢 Agent Registry (Discovery)

To make Cortex discoverable by other agents (e.g., the Router or Orchestrator), it must register itself with the Traylinx Agent Registry.

Registration Payload

On startup, Cortex should send a heartbeat/registration request to the Registry.

Endpoint: POST /a2a/registry/register

Payload:

{
  "envelope": {
    "message_id": "reg-001",
    "sender_agent_key": "traylinx-cortex",
    "timestamp": "2025-11-27T10:00:00Z"
  },
  "action": "registry.register",
  "payload": {
    "agent_key": "traylinx-cortex",
    "name": "Traylinx Cortex",
    "description": "The cognitive core providing unified memory and conversation management.",
    "endpoint_url": "http://traylinx-cortex:8000",
    "capabilities": [
      {
        "key": "domain",
        "value": "conversation",
        "description": "Handles general conversational flows"
      },
      {
        "key": "feature",
        "value": "memory",
        "description": "Provides short-term and long-term memory storage"
      },
      {
        "key": "feature",
        "value": "llm-proxy",
        "description": "Proxies requests to LLMs with context injection"
      }
    ],
    "version": "2.0.0"
  }
}

Discovery by Others

Other agents can find Cortex by querying the Registry for the conversation domain.

Query:

{
  "envelope": {...},
  "action": "registry.query",
  "payload": {
    "capabilities": [
      {"key": "domain", "value": "conversation"}
    ]
  }
}


5. 🔄 A2A Communication Flow

Here is how a typical interaction flows through the system:

sequenceDiagram participant Agent as Calling Agent participant Cortex as Traylinx Cortex participant Sentinel as Traylinx Sentinel participant LLM as LLM Provider Note over Agent, Cortex: 1. Agent sends A2A request Agent->>Cortex: POST /a2a/conversation/chat (with envelope) Note over Cortex, Sentinel: 2. Cortex validates token Cortex->>Sentinel: Introspect Token Sentinel-->>Cortex: Token Valid (Agent: my-agent) Note over Cortex: 3. Cortex retrieves Memory (STM + LTM) Note over Cortex, LLM: 4. Cortex calls LLM Cortex->>LLM: Generate Response (Prompt + Context) LLM-->>Cortex: AI Response Note over Cortex: 5. Cortex saves interaction to Memory Note over Cortex, Agent: 6. A2A response with envelope Cortex-->>Agent: 200 OK (A2A Response)

6. 🏥 Health Endpoints

Cortex exposes health endpoints for orchestration systems:

Endpoint Purpose Response
GET /health Liveness probe {"status": "ok"}
GET /health/live Detailed health {"status": "healthy", "checks": {...}}
GET /ready Readiness probe (K8s) {"status": "ready"} or 503

Readiness Check Logic:

@router.get("/ready")
async def readiness():
    postgres_ok = await check_postgres()
    redis_ok = await check_redis()

    if postgres_ok and redis_ok:
        return {"status": "ready"}
    else:
        raise HTTPException(status_code=503, detail="Not ready")


7. 🛠️ Implementation Checklist

Authentication & Security

  • [ ] Install SDK: Add traylinx-auth-client to pyproject.toml
  • [ ] Env Variables: Configure SENTINEL_URL, REGISTRY_URL, CLIENT_ID, CLIENT_SECRET, AGENT_USER_ID
  • [ ] Middleware: Add A2A Auth middleware to FastAPI app
  • [ ] Verify Headers: Ensure Content-Type and auth headers are validated

Service Discovery

  • [ ] Lifecycle Hook: Add on_startup handler to register with Agent Registry
  • [ ] Heartbeat: Setup background task to send heartbeats to Registry every 30s
  • [ ] Graceful Shutdown: Deregister from Registry on shutdown

A2A Protocol

  • [ ] Envelope Parsing: Implement A2A envelope validation
  • [ ] Correlation IDs: Propagate message_id to correlation_id in responses
  • [ ] Error Format: Return errors in A2A envelope format

8. 🐛 Troubleshooting

A2A Authentication Failures

Symptoms: 401 Unauthorized responses

Check: 1. Valid access_token from Sentinel (not expired) 2. Valid agent_secret_token for your agent 3. Matching X-Agent-Key header with token's agent 4. Correct Content-Type header

# Test token validity
curl -X POST ${SENTINEL_URL}/introspect \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -d "token=${ACCESS_TOKEN}"

Connection Issues

# Test Cortex health
curl http://localhost:8000/health

# Test readiness
curl http://localhost:8000/ready

# Check detailed health
curl http://localhost:8000/health/live

Invalid A2A Format

Symptoms: 400 Bad Request with validation errors

Check: 1. envelope object present with required fields 2. action field matches endpoint 3. payload contains required data 4. Timestamps in ISO 8601 format


9. 🚦 Production Checklist

Before deploying Cortex to production:

Infrastructure

  • [ ] Configure production DATABASE_URL and REDIS_URL
  • [ ] Set up database backups and replication
  • [ ] Configure container orchestration (K8s)
  • [ ] Set up load balancer with health checks

Security

  • [ ] Production Sentinel credentials configured
  • [ ] TLS/HTTPS enabled on all endpoints
  • [ ] API keys rotated from development values
  • [ ] PII scrubbing tested with real data patterns

Observability

  • [ ] Log aggregation configured (ELK, Datadog, etc.)
  • [ ] LangSmith/OpenTelemetry tracing enabled
  • [ ] Monitoring alerts for error rates, latency
  • [ ] Cost tracking dashboards configured

Performance

  • [ ] Load test with expected concurrent users
  • [ ] Vector index performance validated
  • [ ] Redis connection pooling configured
  • [ ] Celery worker scaling tested

Reliability

  • [ ] LLM fallback chain tested
  • [ ] Circuit breaker thresholds tuned
  • [ ] Rate limiting configured in Sentinel
  • [ ] Graceful degradation tested

Document Purpose
specs_v2_final.md Complete API specification
implementation_plan_v2_final.md Step-by-step development guide
./QUICK_REFERENCE.md One-page developer cheat sheet
gcam_research.md Architectural background

Built with: FastAPI, LangGraph, LiteLLM, PostgreSQL + pgvector, Redis, Celery


**[← API Reference](././api_reference.md)** | **[Docs Index](./README.md)** | **[Database Schema →](././DATABASE_SCHEMA.md)**