feat(observability): propagate correlation_id end-to-end

X-Correlation-ID was bound to structlog but lost on the MCP→API hop.
MCP shims now forward it; Envelope carries it back to the agent;
audit_log row records it for forensic joins.
This commit is contained in:
Renn F
2026-05-03 08:37:25 +02:00
parent 99eac69aab
commit 074f47a2f9
14 changed files with 446 additions and 81 deletions
+16 -2
View File
@@ -14,6 +14,7 @@ from __future__ import annotations
import json
import os
import uuid
from pathlib import Path
from typing import Any
@@ -28,19 +29,32 @@ ORCHESTRATOR_URL = os.environ.get(
AGENT_ID = os.environ["ROBOCO_AGENT_ID"]
AGENT_ROLE = os.environ["ROBOCO_AGENT_ROLE"]
_HEADERS = {"X-Agent-ID": AGENT_ID, "X-Agent-Role": AGENT_ROLE}
_TIMEOUT = 30
mcp = FastMCP("roboco-do")
log = structlog.get_logger()
def _build_headers() -> dict[str, str]:
"""Build per-call headers including a fresh X-Correlation-ID.
Mirrors flow_server: each MCP call mints its own correlation id so the
orchestrator's middleware can bind it to structlog and the audit row,
and the envelope echoes it back to the agent.
"""
return {
"X-Agent-ID": AGENT_ID,
"X-Agent-Role": AGENT_ROLE,
"X-Correlation-ID": str(uuid.uuid4()),
}
def _post(path: str, body: dict[str, Any]) -> dict[str, Any]:
"""POST a request to the orchestrator and return the JSON envelope."""
with httpx.Client(timeout=_TIMEOUT) as client:
response = client.post(
f"{ORCHESTRATOR_URL}{path}",
headers=_HEADERS,
headers=_build_headers(),
json=body,
)
response.raise_for_status()