{
  "schema_version": "1.3.0",
  "slug": "what-structural-signals-indicate-broken-causal-linkage-between-prompt-spans-tool-spans-and-memory-operations-in-agent-execution-graphs",
  "title": "What structural signals indicate broken causal linkage between prompt spans, tool spans, and memory operations in agent execution graphs",
  "date_of_record": "2026 November 12",
  "scope": "Applies to agent runtimes that emit OpenTelemetry-style spans for LLM prompt invocations, tool/function calls, and memory read/write operations, correlated via trace context and parent-child relationships. Does not apply to single-shot RAG pipelines without tool loops, nor to systems that reconstruct causality purely from application-level logs without span linkage.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/what-structural-signals-indicate-broken-causal-linkage-between-prompt-spans-tool-spans-and-memory-operations-in-agent-execution-graphs.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/what-structural-signals-indicate-broken-causal-linkage-between-prompt-spans-tool-spans-and-memory-operations-in-agent-execution-graphs.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/what-structural-signals-indicate-broken-causal-linkage-between-prompt-spans-tool-spans-and-memory-operations-in-agent-execution-graphs.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1614,
    "python_slice_tokens": 415,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "A trace is *structurally valid* when every span has a resolvable parent within the same trace, and *causally valid* when the parent-child edges actually reflect the execution dependency (the child could not have executed before the parent completed or yielded). These diverge in agent runtimes because spans are frequently emitted by three different instrument...",
    "what_was_observed": "Across several agent runtimes, the tell-tale signatures of broken causal linkage were: 1. **Tool spans parented to the root instead of the prompt span.** The tool executor created its own span from an ambient context rather than the span context passed in the tool-call arguments. The graph looked like a star (root → prompt, root → tool) instead of a chain (root → prompt → tool). Duration arithmetic then showed tool t...",
    "condition_of_validity": "The causal graph is trustworthy only when all of the following hold simultaneously: - Every non-root span's `[start_time, end_time]` is contained within its parent's interval (with a tolerance for clock skew, typically ≤ a few ms). - Every `tool_call_id` in a prompt span's completion maps to exactly one tool span, and that tool span's parent is the prompt sp...",
    "decision_boundary": "Do **not** attempt to repair the graph by re-parenting spans heuristically at query time. Re-parenting by timestamp proximity produces plausible-but-wrong causality and is worse than an honest flat graph, because downstream analyses (critical-path latency, blame attribution, memory-staleness detection) will silently consume fabricated edges. The correct boun...",
    "operational_effect": "When this boundary is enforced, two things change. First, agent debugging shifts from \"the trace looks complete\" to \"the trace is causally sound,\" and failures like stale memory reads become visible as broken read-after-write edges rather than as unexplained answer drift. Second, correlation-integrity errors become a first-class SLO: a rising rate of causall..."
  },
  "matched_failure_symptoms": [
    "OOM_KILL_OR_MEMORY_EXHAUSTION"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "ba71fae5eae753286ad8a941155683d4cc14e60f93dc0ab011d62f2995518485",
    "verified_classes": [
      "CausalCorrelationError",
      "Span"
    ],
    "verified_functions": [
      "validate_causal_graph"
    ],
    "verified_functions_count": 1,
    "defensive_guards_count": 7,
    "raised_exceptions": [
      "CausalCorrelationError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
