Skip to content

guardrails' protection surface is capped at lane-connected nodes — coverage shrinks with every new tool node added #1792

Description

Context

Guardrails (PR #534) is the platform's one AI-safety primitive: prompt injection, PII, content-safety, hallucination checks, block/warn/log policy. It only attaches via data lanes, so it can only ever check one place in a pipeline: whatever feeds the final response node. Every tool node (tool_http_request, tool_slack, tool_gmail, tool_github, tool_pipedrive, tool_gohighlevel, db_postgres/db_mysql-as-tool, tool_filesystem) runs entirely on the control plane, inside an agent's own turn — guardrails never sees it, in any pipeline, no matter how many tools an agent holds.

What

The ratio (actions guardrails can check) / (total actions an agent can take) shrinks with every tool node shipped — not because guardrails weakened, but because the denominator keeps growing. A 3-tool agent today has 1/4 of its actions checked; the same agent with 8 tools next year still has exactly 1/9 checked. The tool catalog is one of the fastest-growing parts of the product. Net effect: real safety coverage trends toward zero as the platform succeeds at adding integrations, with zero code change to guardrails required to cause that decline.

It's also a two-sided miss: guardrails' input-side checks exist to catch poisoned data before an agent acts on it. Since tool calls happen inside the agent's own turn, a poisoned webhook payload or scraped doc can drive a tool call with no check on either the tainted input or the resulting action — the standard indirect-prompt-injection-into-tool-use gap.

Where it lives

  • nodes/src/nodes/guardrails/ — lanes only (answers, documents, questions)
  • Every tool_* / db_*-as-tool node — lanes: {}, invoked only via control
  • agent_crewai_subagentlanes: {} even for its own output, so nothing downstream can gate it either

Repro / trace

Try to build: crewai_subagent (writes content) → guardrails → tool_slack (send). No lane connection is possible between a subagent's tool call and a guardrails node — guardrails can only ever gate what's already been returned to a lane-connected component.

Suggested fix

Let guardrails attach via control directly to a tool node (classType: "guard", from: <tool_id>), running the same policy checks on the agent's tool-call args (pre) and result (post). One guardrails node, reusable across every tool an agent holds — same config surface as today, no per-tool variant needed. guardrails becomes attachable via control in addition to input.

Severity / impact

High and compounding: coverage degrades automatically with every future tool node. One fix (control-plane attachment) closes the gap for the current catalog and everything added after.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions