deerflow2/backend/packages/harness/deerflow
heart-scalpel a72af8ea37
feat(subagents): attribute subagent spans to parent thread's Langfuse session (#3611)
The subagent execution path did not call inject_langfuse_metadata(...)
and built its model with attach_tracing=True, so subagent LLM/tool
spans landed in Langfuse as isolated top-level traces carrying fresh
session ids and the default user. They were findable in the unfiltered
trace list but did not group under the parent thread's session card,
and Langfuse cost attribution for subagent traffic did not line up
with the parent conversation — even though DeerFlow's internal token
accounting (SubagentTokenCollector) was already correct.

Extend the lead-agent tracing wiring to the subagent path so a single
subagent run produces one trace that shares the parent thread's
session_id and user_id, with a subagent:<name> trace name:

- subagents/executor.py: append build_tracing_callbacks() output to
  run_config["callbacks"] (preserving SubagentTokenCollector) and
  call inject_langfuse_metadata(...) with thread_id, user_id, and
  the normalized subagent:<name> trace name. Build the model with
  attach_tracing=False so model-level tracing does not double-count
  with the graph-root callbacks — the same pairing the lead agent
  uses.
- tools/builtins/task_tool.py: resolve user_id via
  resolve_runtime_user_id(runtime) at the parent tool layer (before
  the background thread starts) and thread it through
  SubagentExecutor.__init__, because the _current_user contextvar
  is not guaranteed to survive the _execution_pool boundary.

Trace topology is unchanged: subagent traces remain separate top-level
traces in the same session, not nested as child spans under the lead
trace (Plan B follow-up).

Tests: tests/test_subagent_executor.py::TestSubagentTracingWiring
covers the callback append, the session/user/trace-name injection,
the disabled-langfuse no-op, the DEFAULT_USER_ID fallback, the
empty-name trace-name fallback, and the env-tag emission. Existing
test_create_agent_threads_explicit_app_config_to_model_and_middlewares
now also asserts attach_tracing=False.

Docs: CLAUDE.md Tracing System section documents subagents/executor.py
as a third injection point alongside worker.py and client.py.
2026-06-17 14:36:09 +08:00
..
agents fix(sandbox): merge idempotent sandbox state updates (#3518) 2026-06-13 22:40:48 +08:00
community fix(sandbox): create shell session before retrying on a fresh id (#3577) 2026-06-17 10:21:27 +08:00
config fix(channels): require bound identity for user-owned IM messages (#3578) 2026-06-16 23:04:39 +08:00
guardrails feat(guardrails): add pre-tool-call authorization middleware with pluggable providers (#1240) 2026-03-23 18:07:33 +08:00
mcp fix(mcp): close stdio sessions on their owning loop to avoid cross-task cancel-scope error (#3379) (#3392) 2026-06-07 21:37:30 +08:00
models feat(models): add StepFun reasoning model adapter (#3461) 2026-06-09 18:01:43 +08:00
persistence fix(channels): make runtime provider state authoritative (#3580) 2026-06-17 07:45:46 +08:00
reflection refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
runtime fix(history): strip base64 image data from REST endpoint responses (#3535) 2026-06-13 08:58:19 +08:00
sandbox fix(sandbox): persist lazily-acquired sandbox state via Command (#3464) 2026-06-11 17:50:36 +08:00
skills fix(skills): keep skill archive installation off the event loop (#3505) 2026-06-12 15:17:40 +08:00
subagents feat(subagents): attribute subagent spans to parent thread's Langfuse session (#3611) 2026-06-17 14:36:09 +08:00
tools feat(subagents): attribute subagent spans to parent thread's Langfuse session (#3611) 2026-06-17 14:36:09 +08:00
tracing fix(tracing): propagate session_id and user_id into Langfuse traces (#2944) 2026-05-21 16:49:31 +08:00
uploads fix upload file size contract (#3408) 2026-06-06 15:12:17 +08:00
utils fix(skills): harden slash skill activation across chat channels (#3466) 2026-06-09 23:07:17 +08:00
__init__.py refactor: split backend into harness (deerflow.*) and app (app.*) (#1131) 2026-03-14 22:55:52 +08:00
client.py feat(memory): add memory.token_counting config to avoid tiktoken network dependency (#3429) (#3465) 2026-06-10 23:26:15 +08:00