Repository navigation
Title #3443
Description
letta 0.16.8 (final release): approval resume skips ToolRules enforcement — rule-violating tool calls wrapped as approval requests execute after user approval
Note for triage: per this repository's SECURITY.md, the V1 Python server is retired and receives no fixes. This report is published for the record and for users still running the final
letta0.16.8 release (PyPI, uploaded 2026-05-14), which is affected.
Summary
In letta 0.16.8 (across all three agent generations — v1/v2/v3), when a tool call violates the ToolRulesSolver allow-set (run_first / constrain_child_tools / conditional / max_count_per_step) and the tool carries a RequiresApprovalToolRule, the agent wraps the call as an approval request instead of surfacing the rule violation. The approval UI never shows that the call is rule-violating. After a human approves, the resume path evaluates:
tool_rule_violated = name not in valid_tool_names and not is_approval_response— the and not is_approval_response clause suppresses the rule-violation verdict on the approval path, so the rule-rejected call executes and is registered in tool_call_history.
Root cause
letta/agents/letta_agent_v3.py:1681-1709— the approval branch precedes the rule-violation check; step 2 wraps rule-violating calls as approval requestsletta/agents/letta_agent_v3.py:1780— step 5a: the clause aboveletta/agents/letta_agent.py:1780/:1797(v1) andletta/agents/letta_agent_v2.py:1138/:1156(v2) — identical patternletta/helpers/tool_rule_solver.py:96-130, 186-188—valid_tool_namescomputation
Reproduction (fully offline, real letta classes)
Harness builds a real LettaAgentV3 (via __new__, no LLM/network), a ToolRulesSolver with InitToolRule(planner) + RequiresApprovalToolRule(guarded_tool), and a real LLMConfig:
- Control:
other_toolviolates rules without an approval rule → 0 executions, error tool result (fail-closed, correct) - Experiment:
guarded_toolviolates rules withRequiresApproval→ an approval request is produced (the violation is not exposed to the approver) → after approval resume (is_approval_response=True) → the tool executes once and is registered
Full offline harness available on request.
Impact
One human approval of an innocuous-looking wrapped call (whose rule violation is hidden from the approval UI) authorizes the rule-violating tool family; subsequent prompt-injected calls of the same shape skip both the rules and the approval. Both the RequiresApprovalToolRule contract ("runs only with explicit approval") and the ToolRulesSolver contract ("only valid tools run") break on the approval path.
Since this server is EOL and unfixed, users of letta==0.16.8 should treat any RequiresApproval-gated tool as effectively unguarded after its first approval, or migrate off the retired server.
Suggested fix (for any fork/reintroduction)
Evaluate tool_rule_violated before the approval branch and reject rule-violating calls regardless of approval resume — i.e. drop the and not is_approval_response clause — and surface the violation inside the approval payload so the approver knows the call is out of policy.
Credit
Chengzhi Yi — yimou@hust.edu.cn — GitHub @Tardfyou
This finding is part of an academic study on verdict-to-effect fidelity in LLM agent frameworks (publication in preparation). Please credit accordingly.
Environment
letta 0.16.8 (latest PyPI release, uploaded 2026-05-14; Python 3.12)
Activity
github-actions commentedon Sep 16, 2026
This issue was automatically closed because it does not meet our submission requirements.
What failed:
To submit an issue, please:
If you believe this was a mistake, please reach out on Discord.