Tracing & Audit Logging
When an LLM workflow is blocked or a step fails unexpectedly, the first question is always "why?" Tracing and audit logging bridge the gap between your orchestrator's execution trace and AxonFlow's governance decisions. The trace_id field links a WCP workflow to the same run in Langsmith, Datadog, or OpenTelemetry, so you can see both the execution path and the policy decisions in a single investigation.
Tracing Integration
Why trace_id Matters
External orchestrators like LangGraph generate their own trace or run identifiers. Without linking those to AxonFlow workflows, debugging requires manually correlating timestamps across two systems. The trace_id field solves this by storing the external identifier directly on the AxonFlow workflow record.
When a LangGraph run is blocked at step 3, you can look up the Langsmith run ID, query AxonFlow workflows by that same trace_id, and immediately see which policy blocked which step, what conditions matched, and what the step's input data contained. This is particularly valuable in production incidents where multiple workflows execute concurrently and timestamp-based correlation is unreliable.
Setting trace_id
Pass trace_id when creating a workflow. The value is freeform (up to 255 characters) and typically contains a run ID from your observability platform.
curl -X POST http://localhost:8080/api/v1/workflows \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-d '{
"workflow_name": "code-review-pipeline",
"source": "langgraph",
"trace_id": "langsmith-run-abc123"
}'
The trace_id is returned in the create response and preserved in all subsequent status queries, including the list workflows endpoint.
SDK Usage
All four SDKs and the LangGraph adapter accept trace_id at workflow creation time.
# Python SDK
workflow = await client.create_workflow(
CreateWorkflowRequest(
workflow_name="research-agent",
source=WorkflowSource.LANGGRAPH,
trace_id="langsmith-run-abc123",
)
)
print(workflow.trace_id) # "langsmith-run-abc123"
# LangGraph adapter
async with adapter:
await adapter.start_workflow(trace_id="datadog-trace-xyz")
// Go SDK
workflow, _ := client.CreateWorkflow(axonflow.CreateWorkflowRequest{
WorkflowName: "research-agent",
Source: axonflow.WorkflowSourceLangGraph,
TraceID: "otel-trace-456",
})
// TypeScript SDK
const workflow = await axonflow.createWorkflow({
workflow_name: "research-agent",
source: "langgraph",
trace_id: "otel-trace-456",
});
// Java SDK
CreateWorkflowResponse workflow = client.createWorkflow(
CreateWorkflowRequest.builder()
.workflowName("research-agent")
.source(WorkflowSource.LANGGRAPH)
.traceId("otel-trace-456")
.build()
);
Filtering by trace_id
To find all AxonFlow workflows associated with a specific external trace, filter the list endpoint by trace_id. This is useful when a single external run spawns multiple AxonFlow workflows, or when you need to verify that a specific run was governed correctly.
curl "http://localhost:8080/api/v1/workflows?trace_id=langsmith-run-abc123" \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
workflows = await client.list_workflows(
ListWorkflowsOptions(trace_id="langsmith-run-abc123")
)
Audit Logging
Every workflow operation is automatically logged to the audit trail. The audit system records the full lifecycle of each workflow, from creation through every gate check to the terminal state. These records persist independently of the workflow data and cannot be modified after creation.
What Gets Logged
The WCP audit logger records six distinct operation types. Each entry includes the workflow ID, workflow name, tenant ID, client ID, user ID, and operation-specific metadata.
| Operation | request_type Value | Metadata Included |
|---|---|---|
| Workflow created | workflow_created | Source, trace_id (if provided) |
| Step gate check | workflow_step_gate | Step type, model, provider, decision (allow/block/require_approval), number of policies evaluated, number of policies matched, tool_name and tool_type (when tool_context is present) |
| Step completed | workflow_step_completed | Step name, step ID |
| Workflow completed | workflow_completed | Total steps executed |
| Workflow aborted | workflow_aborted | Abort reason |
| Workflow failed | workflow_failed | Failure reason |
The step gate audit entry is the most detailed. It captures every policy that was evaluated (not just the ones that matched), the final decision, and the reason. When per-tool governance is used, the tool name and tool type are included in the audit metadata.
A Complete Audit Trail Example
Consider a three-step workflow where the second step is blocked by policy. The audit trail would contain these entries in order:
- workflow_created --
workflow_name: "data-pipeline",source: "langgraph",trace_id: "ls-run-789" - workflow_step_gate --
step_name: "extract-data",step_type: "connector_call",decision: "allow",policies_evaluated: 3,policies_matched: 0 - workflow_step_completed --
step_name: "extract-data",step_id: "step-1-extract-data" - workflow_step_gate --
step_name: "transform-with-gpt4",step_type: "llm_call",model: "gpt-4",decision: "block",policies_evaluated: 3,policies_matched: 1 - workflow_aborted --
reason: "Step transform-with-gpt4 blocked: GPT-4 not allowed in production workflows"
Each entry has a timestamp, making it possible to reconstruct the exact sequence of governance decisions for any workflow execution.
Querying Audit Logs
Use the SDK audit search methods to query workflow audit records. All operations are recorded in the audit_logs table with the workflow ID as the request_id.
# Python SDK
from axonflow.types import AuditSearchRequest
from datetime import datetime, timedelta, timezone
response = await client.search_audit_logs(
AuditSearchRequest(
start_time=datetime.now(timezone.utc) - timedelta(hours=1),
limit=100,
)
)
# Filter entries for a specific workflow
for entry in response.entries:
if entry.request_id == workflow.workflow_id:
print(f"[{entry.timestamp}] {entry.request_type}: {entry.details}")
// Go SDK
auditLogs, _ := client.SearchAuditLogs(ctx, &axonflow.AuditSearchRequest{
StartTime: &startTime,
Limit: 100,
})
for _, entry := range auditLogs.Entries {
if entry.RequestID == workflowID {
fmt.Printf("[%s] %s\n", entry.Timestamp, entry.RequestType)
}
}
For tenant-scoped queries, use GetAuditLogsByTenant to retrieve all audit records for a specific tenant without needing to know individual workflow IDs.
Tool Call Audit Endpoint
For auditing individual tool or function calls outside of the WCP lifecycle (for example, standalone MCP tool invocations that are not part of a registered workflow), use the dedicated tool call audit endpoint:
POST /api/v1/audit/tool-call
This endpoint records tool call details including the tool name, input, output, and policy evaluation results in the audit trail. It is useful when you need to audit tool usage that flows through AxonFlow's MCP connectors but is not governed by a WCP workflow.
Compliance and Regulatory Requirements
The audit trail produced by WCP directly supports several regulatory frameworks that require logging of automated decision-making systems.
EU AI Act (Article 12) requires that high-risk AI systems maintain logs of their operation, including inputs, outputs, and the decisions made at each stage. The WCP audit trail captures every governance decision, the policies that contributed to it, and the step context, providing the technical record required for Article 12 compliance.
RBI (Reserve Bank of India) guidelines for AI in financial services require audit trails showing that automated systems operate within defined governance boundaries. Every blocked step and every approval requirement is recorded with timestamps, policy identifiers, and tenant context.
SOC 2 Type II audits require evidence that access controls and governance mechanisms are consistently enforced. The immutable audit trail, combined with trace_id correlation to external systems, provides the evidence chain for SOC 2 control objectives.
The key property that supports all of these frameworks is completeness: every step gate check is logged regardless of the decision. Allowed steps are logged just as thoroughly as blocked ones. This means auditors can verify not just that governance was enforced when violations occurred, but that it was consistently applied to all workflow steps.
Verifying Audit Logs
See the workflow-policy examples for complete working examples that demonstrate audit log verification after workflow operations.
For more details on general audit logging capabilities, see Audit Logging.
