Skip to main content

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.

Operationrequest_type ValueMetadata Included
Workflow createdworkflow_createdSource, trace_id (if provided)
Step gate checkworkflow_step_gateStep 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 completedworkflow_step_completedStep name, step ID
Workflow completedworkflow_completedTotal steps executed
Workflow abortedworkflow_abortedAbort reason
Workflow failedworkflow_failedFailure 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:

  1. workflow_created -- workflow_name: "data-pipeline", source: "langgraph", trace_id: "ls-run-789"
  2. workflow_step_gate -- step_name: "extract-data", step_type: "connector_call", decision: "allow", policies_evaluated: 3, policies_matched: 0
  3. workflow_step_completed -- step_name: "extract-data", step_id: "step-1-extract-data"
  4. workflow_step_gate -- step_name: "transform-with-gpt4", step_type: "llm_call", model: "gpt-4", decision: "block", policies_evaluated: 3, policies_matched: 1
  5. 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.