docs/subagents.mdXem bản gốc Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.
Chất phụ
SubAgents cho phép một agent ủy thác các nhiệm vụ độc lập cho các agent con được đặt tên. Nó cần một chuỗi SubAgent các mục và hiển thị một delegate_task(agent_name, task) công cụ. Mỗi ủy quyền sẽ điều hành tổng đài viên phụ đã chọn theo cách riêng của mình -- với lịch sử tin nhắn riêng, do đó, nó không bao giờ nhìn thấy cuộc hội thoại chính -- và trả kết quả đầu ra của nó cho cấp trên.
Mặc dù Pydantic AI Harness có trên các bản phát hành 0.x nhưng API có thể thay đổi giữa các bản phát hành nhỏ; khi đó, cảnh báo ngừng sử dụng và hướng dẫn di chuyển ghi chú phát hành sẽ cho bạn (hoặc người đại diện của bạn) biết chính xác cách nâng cấp. Xem chính sách phiên bản.
vấn đề
Một agent duy nhất thực hiện mọi việc sẽ tích lũy được một bộ công cụ lớn và một bối cảnh dài. Việc phân chia công việc giữa các subagent chuyên biệt sẽ giúp mỗi bối cảnh tập trung, nhưng việc sắp xếp ủy quyền theo cách thủ công có nghĩa là viết một công cụ cho mỗi agent, chuyển tiếp các phần phụ, phân luồng giới hạn sử dụng và cho mô hình biết những gì nó có thể ủy quyền.
Giải pháp
SubAgents mất một chuỗi SubAgent các mục và hiển thị một delegate_task(agent_name, task) công cụ. Mỗi ủy quyền sẽ điều hành tổng đài viên phụ đã chọn theo cách riêng của mình -- với lịch sử tin nhắn riêng, do đó, nó không bao giờ nhìn thấy cuộc hội thoại chính -- và trả kết quả đầu ra của nó cho cấp trên. Các subagent khả dụng được liệt kê trong lời nhắc hệ thống dưới dạng lệnh tĩnh, do đó danh sách vẫn ở tiền tố được lưu trong bộ nhớ đệm.
from pydantic_ai import Agent
from pydantic_ai_harness import SubAgent, SubAgents
researcher = Agent('anthropic:claude-sonnet-4-6', name='researcher', description='Researches a topic and reports findings')
writer = Agent('anthropic:claude-sonnet-4-6', name='writer', description='Turns notes into polished prose')
orchestrator = Agent(
'anthropic:claude-opus-4-7',
capabilities=[SubAgents(agents=[SubAgent(researcher), SubAgent(writer)])],
)
result = orchestrator.run_sync('Research the history of TLS and write a one-paragraph summary.')
print(result.output)
Tên của đại biểu -- cách mô hình gốc đề cập đến nó và cách nó được liệt kê trong lời nhắc -- là tên riêng của đại diện name, hoặc một SubAgent(name=...) ghi đè. Hai đại diện giải quyết cùng tên là một lỗi và một đại diện không có tên và không có ghi đè sẽ bị từ chối.
công cụ
| Công cụ | Mục đích |
|---|---|
delegate_task(agent_name, task) | Chạy subagent được đặt tên trên một tác vụ độc lập và trả về kết quả đầu ra của nó. |
- subagent chạy với lịch sử tin nhắn của chính nó, vì vậy
taskphải có tính tự chủ. - Một ẩn số
agent_nametăng lênModelRetry, do đó mô hình có thể tự sửa. - Kết quả trả về cho cha mẹ là
str(result.output). - Với một
modelsmenu được cấu hình, công cụ sẽ mất thêmmodellập luận (xem bên dưới).
Deps, cách sử dụng, công cụ và khả năng
- Deps được chuyển tiếp. Chạy gốc
depsđược chuyển đến từng subagent, vì vậy các subagent chia sẻ thông tin của agent mẹAgentDepsT(được thực thi bằng chữ ký loại -- mỗi subagent là mộtAbstractAgent[AgentDepsT, Any]). - Việc sử dụng được chia sẻ theo mặc định. Của cha mẹ
usageđược chuyển cho mỗi lần chạy subagent, do đó việc tổng hợp mức sử dụng token và agent gốcusage_limitsáp dụng trên toàn bộ cây agent. Đặtforward_usage=Falsegiao cho mỗi agent phụ thực hiện công việc hạch toán riêng. - Các công cụ có thể được kế thừa. Với
inherit_tools=True, công cụ riêng của agent mẹ (đăng ký trực tiếp hoặc quatoolsets) được thêm vào mỗi lần chạy của subagent, bên cạnh hoạt động của subagent. Các công cụ do khả năng của cấp độ gốc đóng góp không được kế thừa: chúng bị ràng buộc với các phiên bản khả năng được đăng ký trong lần chạy cấp độ gốc và sẽ đến mà không có các móc nối và hướng dẫn mà chúng phụ thuộc vào. sử dụngshared_capabilitiesđể cung cấp cho các agent phụ một khả năng. Điều này cũng loại trừ chính công cụ ủy quyền, do đó, tổng đài viên phụ không thể tiếp tục ủy quyền nữa. Tắt theo mặc định. - Khả năng có thể được chia sẻ.
shared_capabilitiesđược áp dụng cho mọi hoạt động của subagent -- ví dụ: cung cấp cho tất cả các subagent một lan can bảo vệ, bộ nhớ hoặc khả năng lập kế hoạch chung mà không cần xây dựng lại từng agentAgent. - Các sự kiện của agent phụ có thể được phát trực tuyến. Vượt qua
event_stream_handlervà nó được chuyển tiếp tới mỗi lần chạy của subagent, do đó, các sự kiện công cụ và truyền phát mô hình của subagent sẽ hiển thị cho người gọi (trình xử lý sẽ nhận được thông tin riêng của subagentRunContext).
Điều khiển chạy cho mỗi đại biểu
Mỗi SubAgent có ngân sách riêng nên quyền kiểm soát của một đại biểu không ảnh hưởng đến những người khác. A SubAgent không có bộ điều khiển chạy với SubAgents mặc định.
from pydantic_ai import Agent
from pydantic_ai.usage import UsageLimits
from pydantic_ai_harness import SubAgent, SubAgents
reproducer = Agent('anthropic:claude-sonnet-4-6', instructions='Reproduce the reported bug from a minimal script.')
librarian = Agent('anthropic:claude-sonnet-4-6', instructions='Find relevant docs, issues, and prior art.')
orchestrator = Agent(
'anthropic:claude-opus-4-7',
capabilities=[
SubAgents(
agents=[
SubAgent(reproducer, usage_limits=UsageLimits(request_limit=35), timeout_seconds=600, max_calls=1),
SubAgent(librarian, usage_limits=UsageLimits(request_limit=18), timeout_seconds=300, max_calls=2),
]
)
],
)
| Lĩnh vực | Hiệu ứng |
|---|---|
models | Phím nào của SubAgents menu mô hình mà đại biểu này có thể chạy trên đó và nó chạy trên trình đơn nào theo mặc định: khóa đầu tiên được liệt kê. Xem phần "Lựa chọn mô hình theo mỗi ủy quyền" bên dưới. |
usage_limits | Ngân sách yêu cầu/token cho một ủy quyền. Đứa trẻ chạy bằng cách tính toán sử dụng của riêng mình, vì vậy ngân sách chỉ tính các yêu cầu và token của đứa trẻ đó (không phải của cha mẹ hoặc anh chị em của con), ngay cả khi forward_usage=True. Sự đánh đổi: token của con đó không còn được tổng hợp vào token của cha mẹ nữa usage. Đạt được ngân sách là một kết quả nhẹ nhàng (xem bên dưới), không phải là một bước dừng UsageLimitExceeded. |
timeout_seconds | Ngân sách đồng hồ treo tường cho một phái đoàn. Khi trẻ vượt quá giới hạn đó, hoạt động chạy của xe sẽ bị hủy và phụ huynh sẽ nhận được thông báo lái nhẹ thay vì bám chặt vào trẻ. Của đứa trẻ bị hủy bỏ event_stream_handler (nếu có) dừng nhận sự kiện mà không có sự kiện đầu cuối. |
max_calls | Số lần ủy quyền tối đa cho tổng đài viên phụ này trong mỗi lần chạy chính. Sau khi đạt được, các ủy quyền tiếp theo sẽ trả lại một thông báo đã cạn kiệt ngân sách mà không cần chạy con. Số lượng được giới hạn trong một Agent.run (a run_id) và bị xóa khi nó kết thúc, do đó, mỗi cấp độ gốc sẽ chạy và mỗi cấp độ của cây lồng nhau sẽ lập ngân sách một cách độc lập. |
on_failure | Một thông báo chỉ đạo được trả về cho phụ huynh về bất kỳ sự xuống cấp phần mềm nào của đại biểu này, thay cho mặc định tích hợp sẵn. Việc thiết lập nó cũng làm cho các lỗi ở trẻ em trở nên nhẹ nhàng hơn (xem bên dưới). |
contain_errors | Liệu một sự cố không mong muốn trong đại biểu này có bị phát hiện và trả về cho thành phần mẹ dưới dạng giới hạn hay không ModelRetry thay vì hủy bỏ lần chạy gốc (xem bên dưới). Bỏ đặt kế thừa SubAgents(contain_errors=...) mặc định (tắt). |
Lựa chọn mô hình cho mỗi ủy quyền
Người điều phối biết nhiệm vụ đó khó khăn như thế nào vào thời điểm họ viết bản tóm tắt, vì vậy đây là nơi thích hợp để quyết định mô hình nào sẽ thực hiện nhiệm vụ đó. Cấu hình một models menu và công cụ đại biểu đạt được model đối số đặt tên cho một trong các khóa của nó.
from pydantic_ai import Agent
from pydantic_ai.settings import ModelSettings
from pydantic_ai_harness import SubAgent, SubAgents
from pydantic_ai_harness.subagents import ModelOption
reviewer = Agent('anthropic:claude-sonnet-4-6', name='reviewer', description='Reviews a diff')
linter = Agent('anthropic:claude-sonnet-4-6', name='linter', description='Runs the linter and reports failures')
orchestrator = Agent(
'anthropic:claude-opus-4-7',
capabilities=[
SubAgents(
agents=[SubAgent(reviewer), SubAgent(linter, models=['fast'])],
models={
'fast': 'anthropic:claude-haiku-4-5',
'standard': 'anthropic:claude-sonnet-4-6',
'deep': ModelOption(
'anthropic:claude-opus-4-7',
description='hard reasoning, multi-file changes',
settings=ModelSettings(thinking='xhigh'),
),
},
)
],
)
- Tắt theo mặc định. Không có
modelsthực đơnmodelđối số hoàn toàn không có trong lược đồ công cụ và mọi ủy quyền đều chạy chính xác như trước đây. - Các phím là giao diện. Chúng được liệt kê trong lời nhắc hệ thống cùng với mô hình và mô tả của từng mục nhập, đồng thời lược đồ công cụ cung cấp chúng dưới dạng enum, do đó, mô hình sẽ chọn từ menu thay vì tạo tên mô hình. Đặt tên cho công việc (
'fast','deep'), không dành cho nhà cung cấp. - Mục nhập là mô hình hoặc
ModelOption.ModelOption(model, description=..., settings=...)thêm gợi ý định tuyến và mỗi tùy chọnModelSettings, vì vậy một phím có thể có nghĩa là "cùng một mô hình, nhiều suy nghĩ hơn". Các cài đặt đó hợp nhất với chính subagentmodel_settings, giữ các phần mà tùy chọn không được đặt. - Thứ tự giải quyết. Khóa cấp trên được chuyển, nếu không thì khóa được phép đầu tiên của đại biểu (xem bên dưới), nếu không thì mô hình của chính đại biểu, nếu không thì mô hình của cấp trên chạy.
- Một đại biểu có thể bị hạn chế.
SubAgent(linter, models=['fast'])chân ủy quyền chofast: khóa được liệt kê đầu tiên là khóa mà nó chạy khi khóa cha vượt qua khôngmodel, và những người khác bị từ chối với mộtModelRetry. Hạn chế được hiển thị trong danh sách nhắc nhở (- linter: Runs the linter (models: fast)). Việc giới hạn một phím mà menu không xác định là mộtValueErrorlúc xây dựng. - Khóa bị từ chối không mất phí. Khóa không xác định hoặc không có sẵn sẽ xuất hiện dưới dạng
ModelRetryliệt kê các tùy chọn hợp lệ, trước đại biểumax_callsngân sách được tính phí.
Xử lý lỗi
kết quả mềm trả về thông báo chỉ đạo cho cấp độ gốc dưới dạng kết quả của công cụ thông thường, do đó, mô hình của nó sẽ đọc thông báo và quyết định việc cần làm tiếp theo (thay vì ủy quyền lại ngay lập tức, điều này ModelRetry lời mời). Đã hết thời gian chờ, đã đạt đến usage_limits ngân sách và cạn kiệt max_calls ngân sách luôn mềm mại. Khi nào on_failure được đặt, thông báo mà nó mang theo sẽ thay thế mặc định tích hợp cho những kết quả này.
Chạy subagent không thành công với lỗi mô hình mềm (ModelRetry, UnexpectedModelBehavior, ví dụ: nó đã hết số lần thử lại), theo mặc định, được chuyển đổi thành ModelRetry cho cha mẹ -- để mô hình của cha mẹ thấy Sub-agent '<name>' failed: ... và có thể phản ứng bằng cách ủy quyền lại. Công cụ ủy quyền mặc định là tool_retries=2, do đó cha mẹ chỉ hủy bỏ sau nhiều lần đại biểu liên tiếp thất bại; bộ đếm sẽ đặt lại sau khi ủy quyền thành công. Tăng tool_retries để chịu đựng một subagent dễ bong tróc hơn, hoặc thiết lập None để kế thừa các lần thử lại công cụ mặc định của agent gốc. Đặt on_failure để một đại biểu làm cho các lỗi của nó trở nên nhẹ nhàng hơn: lỗi con trả về on_failure tin nhắn như một kết quả công cụ bình thường.
Lỗi cứng lan truyền để dừng toàn bộ quá trình chạy. A UsageLimitExceeded từ một đứa trẻ có no mỗi đại biểu usage_limits (do đó nó chia sẻ kế toán của cha mẹ) nghĩa là toàn bộ cây hết ngân sách và nhân giống; một đứa trẻ đạt được của riêng mình usage_limits mềm như trên.
Một sự cố bất ngờ -- bất kỳ ngoại lệ nào khác mà trẻ đưa ra, chẳng hạn như nhà cung cấp ModelAPIError/FallbackExceptionGroup hoặc đồng bằng ValueError từ một đối số công cụ xấu -- truyền bá theo mặc định và hủy bỏ quá trình chạy gốc. Đặt contain_errors=True (theo đại biểu, hoặc theo SubAgents mặc định) để bắt nó và trả lại cho cha mẹ dưới dạng giới hạn ModelRetry thay vào đó, do đó một sự cố của đại biểu không thể hủy bỏ toàn bộ quá trình chạy. Ngăn chặn vẫn ồn ào: ngoại lệ gửi thông báo thử lại (Sub-agent '<name>' crashed: ...), nó được ghi lại thông qua tiêu chuẩn logging mô-đun và tool_retries vẫn còn giới hạn liên tiếp đâm vào một vụ phá thai. Điều này trực giao với on_failure -- một sự cố được ngăn chặn luôn tạo ra âm thanh thử lại lớn, không bao giờ là âm thanh nhỏ on_failure return, do đó lỗi thực sự không bao giờ được coi là thành công. Hủy bỏ, chia sẻ UsageLimitExceeded, tín hiệu điều khiển luồng pydantic-ai (CallDeferred, ApprovalRequired, cái Skip* tín hiệu) và UserError luôn lan truyền bất kể contain_errors.
khám phá
Các agent phụ được liệt kê trong lời nhắc hệ thống thông qua get_instructions, sử dụng của mỗi agent description (hoặc một SubAgent(description=...) ghi đè). Một agent phụ không có mô tả chỉ được liệt kê theo tên.
Đang tải subagent từ đĩa
Các định nghĩa agent đánh dấu của repo trở thành đại biểu mà không cần viết bất kỳ Agent mã. Theo mặc định mỗi *.md tệp trong các thư mục thông thường được tải dưới dạng subagent, cùng với thông tin được chuyển rõ ràng agents.
from pydantic_ai import Agent
from pydantic_ai_harness import SubAgents
orchestrator = Agent(
'anthropic:claude-opus-4-7',
capabilities=[SubAgents(inherit_tools=True)], # auto-loads ./.agents/agents/ and ~/.agents/agents/
)
agent_folders kiểm soát các định nghĩa đến từ đâu. Nó mặc định là 'agents', cách bố trí thông thường:
- Tên thư mục
str(mặc định'agents'): đối với gốc dự án (cwd) thì gốc gốc, tải từ<root>/.agents/<name>/, rơi trở lại<root>/.claude/<name>/khi nào<root>/.agents/vắng mặt. - Một chuỗi các đường dẫn tải từ chính xác các thư mục đó theo thứ tự.
Nonevô hiệu hóa việc tải đĩa, chỉ hiển thị thông tin được thông qua một cách rõ ràngagents.
định dạng định nghĩa
Một định nghĩa là một tệp đánh dấu với phần đầu tùy chọn:
---
name: researcher
description: Researches a topic and reports findings
tools: Read, Grep
---
You research topics. Report your findings, each with a source.
namelà tên đại biểu (cách cấp trên đề cập đến nó và cách nó được liệt kê). Nó rơi trở lại gốc tên tập tin khi vắng mặt.descriptionthúc đẩy danh sách nhắc nhở.- Phần thân markdown trở thành hướng dẫn của agent.
tools(hoặcallowed-tools) là một chuỗi được phân tách bằng dấu phẩy hoặc danh sách chặn YAML. Xem phần "Công cụ" bên dưới.modelvàcolorbị bỏ qua: mô hình được kế thừa từ cha mẹ (xem bên dưới) vàcolorkhông có pyai tương đương.
Frontmatter được đọc bởi một trình phân tích cú pháp nhỏ, không phụ thuộc, giới hạn ở các khóa đó (pyyaml không phải là sự phụ thuộc khai thác). Frontmatter YAML đầy đủ không được hỗ trợ.
Những mô hình và nỗ lực
Các agent đĩa kế thừa mô hình của lần chạy gốc theo mặc định. Mỗi tổng đài viên, người gọi có thể ghi đè mô hình và đặt mức suy nghĩ/nỗ lực thông qua agent_overrides, được khóa theo tên của agent:
from pydantic_ai_harness import SubAgents
from pydantic_ai_harness.subagents import AgentOverride
SubAgents(
agent_folders='agents',
agent_overrides={'researcher': AgentOverride(model='anthropic:claude-sonnet-4-6', effort='high')},
)
Mọi agent được xây dựng năng lực đều hoạt động ở mức nỗ lực tư duy tối thiểu. MINIMUM_EFFORT_FLOOR và clamp_effort(level, floor=...) người trợ giúp được xuất để người điều phối có thể áp dụng cùng một tầng cho các agent của chính mình (ứng dụng phía người điều phối đó là trách nhiệm của người gọi). clamp_effort bản đồ None/False xuống sàn, lá True (nỗ lực mặc định của nhà cung cấp) không thay đổi và nâng mức cụ thể dưới mức sàn lên tới mức đó. Nỗ lực được áp dụng thông qua pyai's ModelSettings.thinking.
Công cụ
Theo mặc định, agent đĩa không có công cụ nào (inherit_tools là False); đặt inherit_tools=True để cho các công cụ của cha mẹ tiếp cận với nó thông qua inherit_tools cơ chế, trong trường hợp đó tools vấn đề phía trước bị bỏ qua. Thay vào đó, để ánh xạ tên công cụ frontmatter tới các bộ công cụ cụ thể, hãy chuyển một tool_resolver: nó nhận từng tên công cụ (vì vậy nó có thể tôn trọng các mục như Bash(git:*)) và trả về các bộ công cụ cung cấp nó, hoặc None đối với một tên không xác định, tên này sẽ bị bỏ qua kèm theo một cảnh báo.
from pydantic_ai_harness import SubAgents
def resolve(tool_name: str):
return TOOLSETS.get(tool_name) # -> Sequence[AgentToolset[object]] | None
SubAgents(agent_folders='agents', tool_resolver=resolve)
Ưu tiên
Khi cùng một tên xuất hiện trong nhiều nguồn, tên nào có mức độ ưu tiên cao hơn sẽ thắng và những tên khác bị bỏ qua kèm theo cảnh báo: đã được thông qua một cách rõ ràng agents đầu tiên, sau đó là thư mục dự án, sau đó là thư mục chính (và, đối với một chuỗi đường dẫn rõ ràng, các đường dẫn trước đó trước các đường dẫn sau). Tên trùng lặp trong phạm vi được thông qua rõ ràng agents danh sách vẫn bị lỗi.
Cấu hình
SubAgents(
agents=(), # Sequence[SubAgent[AgentDepsT]] -- each pairs an agent with its run controls
models={}, # Mapping[str, Model | str | ModelOption] -- per-delegation model menu (off when empty)
agent_folders='agents',# folder-name str (convention) | Sequence[Path] | None (disable)
agent_overrides={}, # Mapping[str, AgentOverride] -- per-disk-agent model/effort override
tool_resolver=None, # Callable[[str], Sequence[AgentToolset[object]] | None] -- disk-agent tool mapping
forward_usage=True, # share the parent's usage with sub-agent runs
inherit_tools=False, # expose the parent's own tools to sub-agents (capability tools excluded)
shared_capabilities=(),# capabilities applied to every sub-agent run
event_stream_handler=None, # forwarded to each sub-agent run to stream its events
tool_name='delegate_task',
tool_retries=2, # extra delegate-tool attempts after a sub-agent error before aborting (None inherits the agent default)
contain_errors=False, # default for SubAgent.contain_errors: contain an unexpected crash as a bounded retry
)
SubAgent(
agent, # AbstractAgent[AgentDepsT, Any] -- the child agent to run
name=None, # delegate name; defaults to the agent's own `name`
description=None, # prompt-listing description; defaults to the agent's own `description`
models=None, # Sequence[str] -- menu keys this delegate may run on; the first is its default
usage_limits=None, # per-delegation request/token budget (isolated accounting)
timeout_seconds=None, # per-delegation wall-clock budget
max_calls=None, # max delegations to this sub-agent per parent run
on_failure=None, # steering message for soft degradations of this delegate
contain_errors=None, # contain an unexpected crash as a bounded retry; None inherits the SubAgents default
)
SubAgents không thể tuần tự hóa thông qua thông số agent (nó vẫn tồn tại Agent trường hợp), vì vậy get_serialization_name() trả lại None.
Ghi chú
- agent phụ có thể tự mình có
SubAgents, tạo thành cây Chia sẻusage(mặc định) và đặtusage_limitsở cấp cao nhất để ràng buộc toàn bộ cây. - Phân quyền các vấn đề của mô hình chạy song song dưới dạng subagent độc lập chạy.
Đọc thêm
Tham chiếu API
::: pydantic_ai_harness.subagents.SubAgents
::: pydantic_ai_harness.subagents.SubAgent
::: pydantic_ai_harness.subagents.ModelOption
::: pydantic_ai_harness.subagents.AgentOverride