Docling 仓库中的 Pydantic AI Agent 能力与钩子机制实战指南
【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling
本篇技术文章以 Docling 仓库自带的开发技能参考文档 CAPABILITIES-AND-HOOKS.md 为主体,系统讲解 Pydantic AI 中 Capabilities(能力)与 Hooks(钩子)两大扩展机制:如何用Thinking、WebSearch等 provider 自适应能力组合出可复用的 Agent 行为、如何用装饰器式钩子拦截 Agent 生命周期实现可观测性与审计、以及何时应当通过子类化AbstractCapability构建自定义能力包。读完后,你能够掌握在 Docling 这类大型 Python 项目中为 Agent 添加"随模型/供应商切换而存活"的声明式行为与轻量拦截层的具体做法。
文档定位:Docling 仓库中的开发技能参考
该文档位于仓库根目录.agents/skills/下,属于 building-pydantic-ai-agents 技能 的按需加载参考之一。根据 AGENTS.md 与 Agent Skills 使用文档 的说明,仓库根目录.agents/skills/存放的是开发技能(development skills),面向在 Docling 上做贡献的 AI 编码代理;而随 Python 包分发的docling/.agents/skills/docling/则是使用技能(usage skills),二者职责不同。SKILL.md中的任务路由表明确了本参考文档的触发场景:
当"需要捆绑可复用行为或拦截生命周期事件"时,加载 Capabilities and Hooks。
也就是说,本文的核心读者是在 Docling 项目内构建 Pydantic AI Agent 的开发者:当你想要 provider 自适应的工具行为、或在不引入新抽象的前提下做生命周期拦截时,这份参考就是入口。前置要求为 Python 3.10+(见技能 SKILL.md 的compatibility元数据)。
为 Agent 添加 Capabilities
Capabilities 是"可复用行为的捆绑单元"——可以把工具(tools)、钩子(hooks)、指令(instructions)和模型设置(model settings)打包成一个整体,并自动组合。官方参考给出的基本用法如下:
from pydantic_ai import Agent from pydantic_ai.capabilities import Thinking, WebSearch agent = Agent( 'anthropic:claude-opus-4-6', capabilities=[ Thinking(effort='high'), WebSearch(), ], )参考文档建议优先使用以下五类provider 自适应能力:
Thinking:模型思考/推理,可配置努力等级WebSearch:Web 搜索WebFetch:URL 抓取ImageGeneration:图片生成MCP:MCP 服务器接入
选用判据很明确:当用户希望某种行为在更换模型/供应商后依然成立时,用 capabilities 而不是裸的模型设置。
结合同技能的 架构决策指南 可进一步看到:capabilities 是 Pydantic AI 的主要扩展点,Agent 的两种构建方式都支持它——Python 构造时传入capabilities=...,声明式定义时用Agent.from_file('agent.yaml')或Agent.from_spec({...})。
跨供应商启用 Thinking
参考文档给出了两种等价路径:统一Thinking能力,或thinking模型设置:
from pydantic_ai import Agent from pydantic_ai.capabilities import Thinking agent = Agent('anthropic:claude-opus-4-6', capabilities=[Thinking(effort='high')]) agent = Agent('anthropic:claude-opus-4-6', model_settings={'thinking': 'high'})支持的 effort 取值完整如下:
| 取值 | 含义 |
|---|---|
True | 开启思考(无级别区分) |
False | 关闭思考 |
'minimal' | 最小推理 |
'low' | 低强度推理 |
'medium' | 中等强度推理 |
'high' | 高强度推理 |
'xhigh' | 超高强度推理 |
这里的"provider 自适应"体现在:同一个Thinking(effort='high')声明在不同供应商上会被翻译成该供应商原生支持的思考/推理参数,因此切换openai:、anthropic:、google-gla:等模型前缀时,行为声明无需改动。
用 Hooks 拦截 Agent 生命周期
Hooks提供基于装饰器的生命周期拦截,无需子类化即可挂接 Agent 运行时的各个阶段。参考文档给出的完整示例同时演示了模型请求钩子与工具执行钩子:
from pydantic_ai import Agent, RunContext from pydantic_ai.capabilities.hooks import Hooks from pydantic_ai.models import ModelRequestContext hooks = Hooks() @hooks.on.before_model_request async def log_request(ctx: RunContext[None], request_context: ModelRequestContext) -> ModelRequestContext: print(f'Sending {len(request_context.messages)} messages') return request_context @hooks.on.before_tool_execute(tools=['send_email']) async def audit_tool(ctx, *, call, tool_def, args): print(f'Executing {call.tool_name}') return args agent = Agent('openai:gpt-5.2', capabilities=[hooks])这个示例里有两个值得注意的细节:
- 钩子可以按工具过滤:
@hooks.on.before_tool_execute(tools=['send_email'])只对指定工具生效,配合call.tool_name、tool_def、args等参数可以精确审计敏感操作; - 钩子函数可以返回修正后的值:
before_model_request返回ModelRequestContext、before_tool_execute返回args,意味着拦截层不仅是只读观测,还能在发请求前、执行前修改上下文——这正是参考文档所说"可观测性、审计、轻量拦截"三合一的能力来源。
参考文档列出了六类重要的钩子家族:
- run-level hooks(运行级)
- node-level hooks(节点级)
- model-request hooks(模型请求级)
- tool-validation hooks(工具校验级)
- tool-execution hooks(工具执行级)
- event-stream hooks(事件流级)
而 架构决策指南 进一步给出了这些钩子在执行流上的落点顺序:
before_run → before_model_request → before_tool_execute → after_tool_execute → after_model_request → after_run它对应 Agent 的执行流Agent.run()→UserPromptNode→ModelRequestNode→CallToolsNode→(循环或结束),即钩子可以覆盖从运行开始到每次模型往返、每次工具调用的全部关键节点。
易错点:SKILL.md 的 Common Gotchas 特别提示,.on下的钩子装饰器名不重复on_前缀——应写hooks.on.run_error与hooks.on.model_request_error,而不是hooks.on.on_run_error。
内置能力速查表
结合同目录 ARCHITECTURE.md 的 Built-in Capabilities 对照表,内置能力全景如下(该表额外标注了哪些能力可用于 YAML 声明式定义):
| 能力 | 提供什么 | 可用于 YAML Spec |
|---|---|---|
Thinking | 模型思考/推理,可配置 effort | 是 |
Hooks | 基于装饰器的生命周期钩子注册 | 否 |
WebSearch | Web 搜索——支持时用 builtin,否则本地回退 | 是 |
WebFetch | URL 抓取——支持时用 builtin,否则自定义回退 | 是 |
ImageGeneration | 图片生成——支持时用 builtin,否则自定义回退 | 是 |
MCP | MCP 服务器——支持时用 builtin,否则直连 | 是 |
PrepareTools | 按步骤过滤或修改工具定义 | 否 |
PrefixTools | 包装一个能力并为其工具名加前缀 | 是 |
BuiltinTool | 向 Agent 注册一个 builtin 工具 | 是 |
Toolset | 包装一个AbstractToolset | 否 |
HistoryProcessor | 包装一个消息历史处理函数 | 否 |
从这张表可以推断:Hooks、PrepareTools、Toolset、HistoryProcessor依赖运行时 Python 对象,因此只能在代码中装配;而Thinking、WebSearch、MCP等可声明式能力适合放进 YAML/JSON 规格文件,与 Agent 的其余配置一起版本化管理。
构建自定义 Capability
当"钩子 + 指令 + 工具 + 模型设置"需要作为一个整体复用时,就应当子类化AbstractCapability。参考文档给出的三条适用判据:
- 同一捆绑行为要在多个 Agent 之间复用;
- 单独的
Hooks已经不够(还需要工具、指令或模型设置); - 该行为希望是可安装/可声明式的(installable or declarative)。
架构决策指南中的决策树与之一致:
需要跨 Agent 复用的行为(tools + hooks + instructions)? ├── 是 → 构建自定义 capability(子类化 AbstractCapability) └── 否 → 只是拦截生命周期事件? ├── 是 → 复杂拦截,还需要工具/指令? │ ├── 是 → 子类化 AbstractCapability │ └── 否 → 用 Hooks 能力 + 装饰器 └── 否 → ...(配置文件定义用 Agent.from_file(),加工具用 @agent.tool 等)从源码结构看,AbstractCapability是带依赖泛型的基类:AbstractCapability[AgentDepsT],与Agent[AgentDepsT, OutputDataT]、RunContext[AgentDepsT]构成同一套泛型体系,这意味着自定义能力同样能感知 Agent 的 deps 类型。
参考文档最后给出一条收敛性原则,值得原样遵守:保持自定义能力聚焦(focused)。如果只需要一个工具或一个钩子,不要为此引入 capability——单工具用@agent.tool/Tool(fn),单钩子用Hooks即可,避免为微小行为支付抽象成本。
声明式配置与测试验证
capabilities 也支持声明式定义。SKILL.md 给出了 YAML 规格示例,其中 capabilities 与 Python 构造完全对应:
from pydantic_ai import Agent # agent.yaml: # model: anthropic:claude-opus-4-6 # instructions: You are a helpful research assistant. # capabilities: # - WebSearch # - Thinking: # effort: high agent = Agent.from_file('agent.yaml')模型字符串必须带provider:model-name前缀(如'openai:gpt-5.2'、'anthropic:claude-sonnet-4-6'),无前缀时 Pydantic AI 无法解析供应商——这是 SKILL.md 中明确列出的常见错误之一。
验证钩子与能力是否装配正确时,推荐用TestModel做确定性测试,且必须通过agent.override()上下文管理器替换模型,不能直接给agent.model赋值:
from pydantic_ai import Agent from pydantic_ai.models.test import TestModel my_agent = Agent('openai:gpt-5.2', instructions='...') async def test_my_agent(): """Unit test for my_agent, to be run by pytest.""" m = TestModel() with my_agent.override(model=m): result = await my_agent.run('Testing my agent...') assert result.output == 'success (no tool calls)' assert m.last_model_request_parameters.function_tools == []通过断言last_model_request_parameters(如上面的function_tools),可以确认能力/钩子注入的工具与模型设置确实进入了真实的模型请求参数。
小结与延伸阅读
本篇沿 CAPABILITIES-AND-HOOKS.md 的原始脉络完整覆盖了三层递进式扩展手段,选型结论可以浓缩为一句话:
| 需求 | 手段 |
|---|---|
| 行为需跨模型/供应商存活 | 内置 capabilities(Thinking、WebSearch、WebFetch、ImageGeneration、MCP) |
| 只拦截生命周期、做观测/审计/轻量修正 | Hooks+ 装饰器(run / node / model-request / tool-validation / tool-execution / event-stream 六类家族) |
| 多 Agent 复用、工具+钩子+指令成捆绑 | 子类化AbstractCapability(保持聚焦,勿过度抽象) |
如需继续深入,可沿仓库内这些路径阅读:技能入口 SKILL.md、决策与对照表 ARCHITECTURE.md、工具侧参考 TOOLS-CORE.md、测试与调试 TESTING-AND-DEBUGGING.md,以及 Docling 自身技能体系的设计说明 docs/usage/agent_skills.md。
【免费下载链接】doclingGet your documents ready for gen AI项目地址: https://gitcode.com/GitHub_Trending/do/docling
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考