mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-30 18:05:59 +00:00
* feat: record guardrail decisions in run events Persist security-relevant GuardrailMiddleware outcomes (deny and provider-error fail-open/fail-closed) as middleware:guardrail run events via RunJournal.record_middleware(), mirroring SafetyFinishReasonMiddleware. Recording is best-effort: it reads __run_journal from the runtime context and swallows persistence failures, so tool execution behavior is unchanged. The audit payload records tool name/id, agent id, subagent flag, user role, allow decision, policy id, reason codes/messages, fail_closed mode, and provider_error flag. Tool input/args and identity fields (user_id, oauth_*) are deliberately excluded to avoid persisting the sensitive content being blocked. The fail-closed provider-error branch returns the denied message directly from the except block so it records exactly once and does not fall through to the generic deny branch. * docs: clarify guardrail journal runtime boundary * fix: preserve subagent attribution in guardrail events * test: align guardrail event attribution fixtures * refactor(guardrails): resolve runtime context once per tool call Extract `_resolve_context` and thread the already-resolved context dict through `_build_request` and `_record_guardrail_event` so the getattr/runtime.context chain runs once per wrap_tool_call instead of twice. Also document the `is_subagent` field boundary: native subagents do not inherit __run_journal, so the field is structurally False in persisted records today; custom runtimes may still supply it with attribution. Addresses review feedback on #3837 (context-read-twice cleanup and the is_subagent trade-off note). No behavior change.