mpfaffenberger / mpfaffenberger/code_puppy

pydantic_patches.py: all 6 monkey patches fail silently (except Exception: pass) — if pydantic-ai internals drift, pre_tool_call blocking/guardrails vanish with no warning

Open
#413 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
814
Forks
278
Avg merge
2d 5h
Merged PRs (30d)
76

Description

Problem

code_puppy/pydantic_patches.py (515 lines) is the load-bearing wall of the whole tool-call pipeline, and every patch is wrapped in:

    except ImportError:
        pass
    except Exception:
        pass  # Don't crash on patch failure

(8 occurrences). If pydantic-ai renames _tool_manager.ToolManager, _agent_graph._clean_message_history, or changes _call_tool's signature in a minor release, the patches silently stop applying and Code Puppy degrades in subtle ways: pre/post tool-call hooks stop firing (security-relevant — pre_tool_call is the blocking mechanism for hook policies!), JSON repair stops, claude-code cp_ unprefixing stops (tool calls break), and nobody gets a log line. "Errors should never pass silently."

Specific notes:

  • patch_tool_call_callbacks() (lines ~210-380) replaces three private pydantic-ai internals (get_tool_def, handle_call, _call_tool). The blocking behavior of pre_tool_call hooks — the mechanism run_shell_command blocking and file-permission plugins depend on — lives inside except Exception: pass. If patching fails, hook-based guardrails silently disappear while the app keeps running.
  • The except Exception: pass around the pre_tool_call invocation inside _patched_call_tool (line ~340) also swallows failures of the blocking check itself: if callbacks.on_pre_tool_call raises, the tool executes anyway. For a guard mechanism, fail-open should at least be logged.
  • No version pinning or capability check: patches assume private API shapes but pyproject.toml ranges allow pydantic-ai upgrades.

Suggested fix

  1. Replace silent passes with a logged warning, e.g.:
    except Exception as exc:
        logger.warning(\"pydantic-ai patch %s failed; hook enforcement degraded: %s\",
                       \"patch_tool_call_callbacks\", exc)
  1. Have apply_all_patches() return a dict of {patch_name: bool} and emit a single startup warning listing any failed patches.
  2. Add a smoke test that asserts the patched attributes differ from the originals after apply_all_patches(), so CI catches pydantic-ai API drift at upgrade time.

Filed by Zen Reviewer A (code-puppy-60635a)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in code_puppy/pydantic_patches.py, especially patch_tool_call_callbacks(), _patched_call_tool, and apply_all_patches(), then inspect pyproject.toml's pydantic-ai ranges. Replace silent failures with warnings, return patch outcomes, and add the proposed smoke test asserting patched attributes differ from their originals. Done means patch failures are visible and CI detects pydantic-ai API drift.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
security, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.