README.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.
Pydantic AI Harness
harness yêu thích của agent của bạn, được xây dựng trên Pydantic AI
Pydantic AI Harness là khả năng chính thức và thư viện harness cho Pydantic AI. Mọi AI agent Pydantic đều đã có một harness nhẹ: vòng lặp agent typed, bất kỳ mô hình nào, công cụ của riêng bạn, kết quả đầu ra có cấu trúc. Đối với các agent đơn giản như vậy là đủ. Tuy nhiên, hãy thả lỏng một agent đối với công việc phức tạp, kéo dài (sửa cơ sở mã, nghiên cứu một câu hỏi, chạy hàng giờ mà không cần giám sát) và những gì nó cần xung quanh mô hình sẽ tăng lên: một không gian làm việc để hành động, một kế hoạch nó giữ hiện tại, bộ nhớ truyền qua các phiên, subagent để thực hiện công việc, quản lý bối cảnh có thể duy trì trong giờ thứ 10 và thực thi bền vững vẫn tồn tại sau khi khởi động lại. Pydantic AI Harness vận chuyển harness đó.
Mọi thứ ở đây đều là một nguyên thủy: a khả năng, một đơn vị hành vi agent độc lập mà bạn thêm vào capabilities=[...] trên bất kỳ agent nào. Có 30+ trong số đó và các agent hoàn chỉnh như Coder và Researcher là những khả năng được kết hợp: chúng tách rời nhau theo cách chúng đi cùng nhau. Gắn vào một khối duy nhất, soạn ngăn xếp của riêng bạn hoặc bắt đầu từ toàn bộ coding agent và tách nó ra sau.
Bắt đầu nhanh
Cài đặt với uv:
uv add "pydantic-ai-harness[anthropic]"
from pydantic_ai import Agent
from pydantic_ai_harness import Coder
agent = Agent('anthropic:claude-fable-5', capabilities=[Coder()])
result = agent.run_sync('Find out why tests/test_parser.py fails and fix the bug it caught.')
print(result.output)
#> Found it: `parse()` returned None on empty input instead of raising. Fixed in src/parser.py; tests pass now.
Đó là một coding agent hoàn chỉnh: quyền truy cập tệp có nguồn gốc từ không gian làm việc, vỏ được liệt kê cho phép, định hướng repo, lập kế hoạch, một subagent của Explorer chỉ đọc và quản lý bối cảnh tồn tại trong các phiên dài và chạy ở bất kỳ nơi nào mà AI agent Pydantic chạy. agent.to_cli_sync() mở nó dưới dạng cuộc trò chuyện trong terminal của bạn, agent.to_web() trong trình duyệt và Coder được xuất khẩu coder_agent chạy mà không cần ghi tập tin nào cả, kết hợp với clai (Pydantic AI CLI) và uvx:
uvx --with pydantic-ai-harness clai -a pydantic_ai_harness.coder:coder_agent -m anthropic:claude-fable-5
Mọi mô hình đều hoạt động: trao đổi chuỗi cho bất kỳ nhà cung cấp nào. Cần thêm nữa? Thêm khả năng vào danh sách; đây là cùng một lập trình viên trên gpt-5.6-sol, với tìm kiếm trên web và bộ nhớ phiên chéo:
uv add "pydantic-ai-slim[openai]"
from pydantic_ai import Agent
from pydantic_ai.capabilities import WebSearch
from pydantic_ai_harness import Coder, Memory
from pydantic_ai_harness.memory import FileStore
agent = Agent(
'openai:gpt-5.6-sol',
capabilities=[
Coder(),
WebSearch(), # look up docs and error messages on the web
Memory(FileStore('.agent-memory')), # remembers across sessions
],
)
Kỹ năng (của bạn SKILL.md thủ tục, nạp theo yêu cầu; chỉ nó vào một skills/ thư mục và thêm skills bổ sung), Tìm nạp web, Guardrails và Quy trình làm việc động khe cắm theo cách tương tự; Coder README liệt kê những cặp tốt nhất.
Không có phép thuật: đó là tất cả các khả năng
Coder không phải là một khuôn khổ bên trong khuôn khổ; đó là một CombinedCapability gói các khối giống nhau mà bạn có thể sử dụng trực tiếp. Đây chính xác là agent được xuất khẩu coder_agent cung cấp cho bạn, được viết ra từng khối:
from pathlib import Path
from pydantic_ai import Agent
from pydantic_ai_harness import (
ClearToolResults,
FileSystem,
LLM_API_KEY_ENV_PATTERNS,
Planning,
RepoContext,
Shell,
SubAgent,
SubAgents,
ToolOutputLimits,
WarnNearLimits,
)
allowed_commands = [
'git', 'rg', 'grep', 'find', 'ls', 'cat', 'sed', 'head', 'tail',
'python', 'uv', 'pytest', 'ruff', 'make',
]
explorer = SubAgent(
Agent(
name='explorer',
description='Explore the codebase and answer questions without modifying anything',
instructions='Answer with concrete paths and evidence.',
capabilities=[
FileSystem('.', read_only=True),
RepoContext(workspace_dir=Path('.')),
],
)
)
agent = Agent(
'anthropic:claude-fable-5',
name='coder',
instructions='You are a coding agent built on Pydantic AI.',
capabilities=[
FileSystem('.'), # read/write/edit/search, path-traversal safe
Shell( # allowlisted commands, LLM API keys stripped from their environment
cwd='.',
allowed_commands=allowed_commands,
denied_env_patterns=LLM_API_KEY_ENV_PATTERNS,
),
RepoContext(workspace_dir=Path('.')), # loads AGENTS.md/CLAUDE.md + repo structure
Planning(), # structured task plans the model maintains
SubAgents(agents=[explorer], agent_folders=None), # delegate exploration off the main context
ClearToolResults(max_fraction=0.7), # clears old tool results near the limit
WarnNearLimits(max_context_fraction=0.9), # warns the model before it hits limits
ToolOutputLimits(), # bounds oversized tool results
],
)
Bắt đầu từ harness và loại bỏ những gì bạn không muốn hoặc bắt đầu từ các khối và tích tụ lại; cả hai đều là hạng nhất. Các đối số của hàm tạo (thư mục làm việc, danh sách lệnh cho phép, kích thước cửa sổ) xuyên suốt các khả năng cơ bản.
Khả năng
Mỗi khả năng là một đơn vị độc lập mà bạn có thể tham gia capabilities=[...], và tất cả đều sáng tác, cùng nhau và với chính bạn. Một số đi kèm với pydantic-ai chính nó, phần còn lại với gói này; cột Gói cho biết điều đó. Tổng cộng có hơn 50, được nhóm theo những gì họ cung cấp cho agent của bạn:
harness
Các ngăn agent hoàn chỉnh dưới dạng các khả năng kết hợp thông thường: một lần nhập sẽ cung cấp cho bạn một agent đang hoạt động và bạn có thể tách một trong hai agent đó thành các khối bên dưới.
| Khai thác | Trọn gói | Nó cung cấp những gì |
|---|---|---|
| Coder | Khai thác | Một ngăn xếp coding agent hoàn chỉnh: tệp, shell, ngữ cảnh repo, lập kế hoạch, subagent explorer chỉ đọc và điều khiển ngữ cảnh |
| Researcher | Khai thác | Một ngăn xếp nghiên cứu web hoàn chỉnh: tìm kiếm, tìm nạp trang, nhà nghiên cứu phụ được ủy quyền và đầu ra công cụ giới hạn |
Môi trường thực thi
Không gian làm việc mà agent hành động trong: các tệp mà nó chỉnh sửa và các lệnh mà nó chạy, cục bộ hoặc tách biệt.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Hệ thống tập tin | Khai thác | Đọc, viết, chỉnh sửa, tìm kiếm tập tin dưới gốc; truyền tải đường dẫn và liên kết tượng trưng an toàn, bí mật chỉ đọc |
| Vỏ | Khai thác | Thực thi lệnh với danh sách cho phép, danh sách từ chối, thời gian chờ và tước bỏ thông tin xác thực |
| Hộp cát phương thức | Khai thác | Các lệnh và tập tin trong một Modal hộp cát đám mây |
Công cụ & khả năng bản địa
Các kết nối với các hệ thống bên ngoài không gian làm việc của tổng đài viên và các khả năng mà nhà cung cấp thực thi nguyên bản.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| MCP | Cốt lõi | Kết nối bất kỳ công cụ nào của máy chủ MCP; cục bộ theo mặc định, chọn tham gia trình kết nối gốc của nhà cung cấp |
| Tạo hình ảnh | Cốt lõi | Tạo và chỉnh sửa hình ảnh; nhà cung cấp gốc ở nơi được hỗ trợ, dự phòng agent phụ ở nơi khác |
| StackOne | Khai thác | Hành động trên các tài khoản SaaS được liên kết (HRIS, ATS, CRM, …) thông qua StackOne |
| LocalStack | Khai thác | Môi trường AWS mô phỏng với các công cụ AWS CLI |
| Kính hiển vi | Khai thác | Chạy Macroscope cục bộ xem xét mã và bàn giao kết quả cho agent |
Web & nghiên cứu
Tìm và đọc mọi thứ trên web mở.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Tìm kiếm trên web | Cốt lõi | Tìm kiếm gốc của nhà cung cấp nếu có, dự phòng DuckDuckGo cục bộ ở mọi nơi |
| Tìm nạp web | Cốt lõi | Tìm nạp và đọc URL, gốc hoặc cục bộ |
| X Tìm kiếm | Cốt lõi | Tìm kiếm X; gốc trên xAI, dự phòng agent phụ ở nơi khác |
| Tìm kiếm Exa | Khai thác | Nghiên cứu web qua Exa: tìm kiếm được trích dẫn, đọc toàn trang, chọn tham gia tìm kiếm sâu được trích dẫn |
| agent Exa | Khai thác | Ủy quyền nghiên cứu mở cho API Exa Agent |
| Tìm kiếm trên You.com | Khai thác | Tìm kiếm trên web và đọc trang qua You.com: đoạn trích có liên quan đến truy vấn hoặc đánh dấu toàn trang |
| Nghiên cứu của You.com | Khai thác | Các câu trả lời được trích dẫn và nghiên cứu nhiều bước thông qua API Trả lời, Nghiên cứu và Nghiên cứu Tài chính của You.com |
| Sử dụng trình duyệt | Khai thác | Giao các tác vụ web cho việc sử dụng trình duyệt tự chủ agent điều khiển một trình duyệt thực sự |
| Trình duyệt nhà viết kịch | Khai thác | Tự mình điều khiển một trang Chrome thực sự: điều hướng, nhấp chuột, nhập, đọc và kiểm tra xem trang đó đã làm gì |
Lý luận, lập kế hoạch và ủy quyền
Người đại diện suy nghĩ và phân chia công việc như thế nào.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Suy nghĩ | Cốt lõi | Tư duy mở rộng thích ứng với nhà cung cấp với nỗ lực có thể định cấu hình |
| Kế hoạch | Khai thác | Kế hoạch nhiệm vụ do mô hình sở hữu với lời nhắc trực tiếp an toàn về bộ nhớ đệm |
| subagent | Khai thác | Giao các nhiệm vụ khép kín cho các agent con được đặt tên |
| Quy trình làm việc động | Khai thác | Mô hình này sắp xếp các subagent từ một tập lệnh Python: phân nhánh, chuỗi, bỏ phiếu trong một lệnh gọi công cụ duy nhất, với phần cứng max_agent_calls ngân sách |
| Cố vấn | Khai thác | Hãy để người thực thi tham khảo một mô hình mạnh mẽ hơn trong quá trình thực hiện |
Quản lý bối cảnh
Cách agent sử dụng cửa sổ ngữ cảnh của nó: sự khác biệt giữa một agent xuống cấp trong thời gian dài và một agent không xuống cấp và giữa việc trả tiền cho token N lần hoặc một lần.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Chế độ mã | Khai thác | Mô hình viết một tập lệnh Python gọi nhiều công cụ bên trong Monty hộp cát: một chuyến đi khứ hồi thay vì N và các kết quả trung gian không bao giờ nhập vào cửa sổ ngữ cảnh. Câu trả lời cho sự phình to của token lệnh gọi công cụ |
| Tìm kiếm công cụ | Cốt lõi | Tải các định nghĩa công cụ theo yêu cầu thay vì mang hàng trăm định nghĩa trong mỗi lời nhắc |
| Nén chặt | Cốt lõi | Sự nén chặt của nhà cung cấp trên OpenAI và Anthropic; nhà cung cấp tóm tắt lịch sử phía máy chủ |
| Nén chặt | Khai thác | Các chiến lược bất khả tri về mô hình: xóa kết quả công cụ, cắt xén cửa sổ trượt, tóm tắt LLM, xếp bậc; tất cả đều tương đối với cửa sổ, có báo cáo sử dụng trực tiếp |
| Giới hạn đầu ra của công cụ | Khai thác | Cắt bớt, tràn vào một tệp có thể truy vấn hoặc tóm tắt các công cụ quá khổ trả về tại nguồn |
| Cảnh báo về lỗi bộ đệm | Khai thác | Phát hiện sự cố sập tiền tố bộ đệm nhắc nhở giữa các yêu cầu, từ số của chính nhà cung cấp |
Kiến thức và trí nhớ
Những gì agent biết và ghi nhớ, được tải khi có liên quan thay vì được đưa vào mọi lời nhắc.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Bộ nhớ | Khai thác | Một sổ ghi chép có không gian tên ổn định: đưa vào dấu nhắc có giới hạn, tìm kiếm theo yêu cầu; cửa hàng trong bộ nhớ/tập tin/Postgres |
| Tìm kiếm cuộc trò chuyện | Khai thác | BM25 tìm kiếm theo lịch sử được lưu trữ, bao gồm cả lượt nén bị bỏ |
| Kỹ năng | Khai thác | Tải Kỹ năng agent (SKILL.md) hướng dẫn theo yêu cầu |
| Bối cảnh Repo | Khai thác | Bắt đầu chạy theo định hướng: AGENTS.md/CLAUDE.md + Cấu trúc repository |
| Tài liệu AI Pydantic | Khai thác | Tra cứu tài liệu Pydantic AI theo yêu cầu |
Kiểm soát & an toàn
Giới hạn những gì agent có thể làm và tuân thủ các hướng dẫn.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Guardrails | Khai thác | Xác thực/chặn/xác định lại thông tin đầu vào của người dùng, lệnh gọi công cụ, kết quả công cụ và đầu ra, bao gồm cả mặt nạ bí mật và bộ bảo vệ không đồng bộ song song |
| Người bảo vệ tiêm nhắc nhở | Khai thác | Phân loại kết quả công cụ cục bộ để tiêm nhanh gián tiếp và tùy ý giữ lại các kết quả có rủi ro cao |
| Giới hạn chi tiêu | Khai thác | Ngân sách USD/token đa cửa sổ và theo dõi chi phí trên mỗi phản hồi, trên mỗi mô hình và mỗi đối tượng thuê |
| Phê duyệt công cụ | Cốt lõi | Gắn cờ các lệnh gọi công cụ cần có sự chấp thuận của con người trước khi chúng chạy |
| Xử lý các lệnh gọi công cụ bị trì hoãn | Cốt lõi | Giải quyết các cuộc gọi công cụ trì hoãn phê duyệt theo chương trình |
| Nhắc nhở hệ thống | Khai thác | Đưa lại hướng dẫn vào bộ đệm một cách an toàn giữa chừng để làm mờ dần hướng dẫn |
Tự mở rộng
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Sáng tạo năng lực | Khai thác | agent viết, xác thực và duy trì khả năng mới trong quá trình chạy, được tải trong lần chạy tiếp theo: tự mở rộng với các đơn vị được nhập, có thể kiểm tra thay vì mã tùy ý |
runtime thực thi
Bên ngoài vòng lặp: cách các lần chạy vẫn tồn tại, tồn tại khi xảy ra lỗi cũng như được quan sát và định cấu hình trong quá trình sản xuất.
| Năng lực | Trọn gói | Nó làm gì |
|---|---|---|
| Thực thi lâu bền | Cốt lõi | Các lần chạy vẫn tồn tại sau khi khởi động lại và bị lỗi trên Tạm thời, DBOS, hoặc Tiền bối, với Phục hồi, Kitaru và Luồng khí tích hợp |
| Bước kiên trì | Khai thác | Lưu, khôi phục, tiếp tục (continue_run) và ngã ba (fork_run) chạy; tập tin/phụ trợ SQLite/Mongo |
| Dụng cụ | Cốt lõi | OpenTelemetry GenAI mở rộng cho mọi lệnh gọi mô hình và công cụ; nguyên liệu thô cho Logfire dấu vết |
| Lời nhắc được quản lý | Khai thác | Quay lại hướng dẫn bằng Logfire-lời nhắc được quản lý; phiên bản và triển khai mà không cần triển khai lại |
| Trình thực thi luồng | Cốt lõi | Chạy các công cụ đồng bộ hóa trên nhóm chủ đề được chia sẻ |
Core cũng cung cấp khả năng tùy chỉnh vòng lặp cho các máy chủ sản xuất: Select Model, Giải quyết ID mẫu, Chuẩn bị công cụ / Chuẩn bị công cụ đầu ra, Công cụ tiền tố, Đặt siêu dữ liệu công cụ, Bao gồm lược đồ trả về công cụ, Lịch sử quy trình, Luồng sự kiện xử lý, Tiêm lại lời nhắc hệ thống và Tăng lỗi bộ lọc nội dung.
Và agent cắm vào bất kỳ giao diện nào: ACP (thử nghiệm, Khai thác) phục vụ nó cho các biên tập viên như Zed qua Giao thức khách hàng agent và lõi cung cấp giao diện người dùng trò chuyện trên web, CLI, bộ điều hợp giao diện người dùng (AG-UI, Vercel AI) và giọng nói thời gian thực.
Các gói cộng đồng mở rộng hệ thống khả năng tương tự hơn nữa; xem khả năng của bên thứ ba.
Soạn từ các khối
Một agent nghiên cứu từ các khả năng thông thường -- đây đúng là Researcher, trừ đi các hướng dẫn mặc định ngắn gọn của nó:
from pydantic_ai import Agent
from pydantic_ai.capabilities import WebFetch, WebSearch
from pydantic_ai_harness import SubAgent, SubAgents, ToolOutputLimits
sub_researcher = SubAgent(
Agent(
name='researcher',
description='Research a focused sub-question on the web and report back with findings and source links',
capabilities=[WebSearch(local=True), WebFetch(local=True), ToolOutputLimits()],
)
)
agent = Agent(
'anthropic:claude-fable-5',
capabilities=[
WebSearch(local=True), # native provider search, DuckDuckGo fallback elsewhere
WebFetch(local=True), # read the pages behind the results, native or local
SubAgents(agents=[sub_researcher], agent_folders=None),
ToolOutputLimits(), # fetched pages don't flood the context
],
)
result = agent.run_sync('What changed in the top three Python agent frameworks this month? Cite sources.')
print(result.output)
#> ...
Mọi thứ đều có thể quan sát được: logfire.instrument_pydantic_ai() cung cấp cho bạn dấu vết đầy đủ của mỗi lần chạy: mọi lệnh gọi mô hình và lệnh gọi công cụ, với token và theo dõi chi phí. Đó là OpenTelemetry tiêu chuẩn, vì vậy mọi chương trình phụ trợ OTLP đều hoạt động; Cháy rừng là cách dễ nhất để thấy nó trong quá trình phát triển.
Khi nào bạn cần harness?
"Khai thác" là thuật ngữ của trường cho mọi thứ xung quanh mô hình biến nó thành một agent: vòng lặp, công cụ, quản lý bối cảnh. Hãy tiếp cận gói này khi agent của bạn cần làm nhiều việc hơn vỏ bọc khai thác tinh gọn của lõi: chạm vào tệp, chạy mã, duyệt, ghi nhớ, ủy quyền hoặc duy trì mạch lạc trong suốt runtime kéo dài hàng giờ. Ranh giới giữa các gói là cơ học, không phải là cấp độ trưởng thành: cốt lõi cung cấp các khả năng yêu cầu hỗ trợ mô hình hoặc khung (các công cụ gốc của nhà cung cấp như tạo hình ảnh, các API của nhà cung cấp như nén, tích hợp vòng lặp sâu như tìm kiếm công cụ và các nguyên tắc cơ bản như suy nghĩ, MCP và tìm kiếm trên web) và Harness vận chuyển mọi thứ khác, dưới dạng một gói riêng biệt để các khả năng có thể lặp lại theo tốc độ di chuyển của trường trong khi bản thân Pydantic AI vẫn gọn gàng.
Cài đặt
uv add pydantic-ai-harness
Cài đặt này pydantic-ai-slim với nó, nên nó tự hoạt động; bạn không cần phải cài đặt riêng Pydantic AI. Các nhà cung cấp mô hình và CLI đến từ các tính năng bổ sung chuyển sang Pydantic AI: pydantic-ai-harness[anthropic], [cli]. Một số khả năng cần có phần bổ sung riêng cho các phần phụ thuộc tùy chọn; trang của mỗi khả năng cung cấp dòng cài đặt chính xác. Yêu cầu Python 3.10+.
Xây dựng của riêng bạn
Khả năng là điểm mở rộng chính cho Pydantic AI và mọi khả năng trong repo này đều đóng vai trò là một ví dụ hoạt động. Xuất bản một gói độc lập? Sử dụng pydantic-ai-<name> quy ước đặt tên; xem Gói khả năng xuất bản.
Đóng góp
Chúng tôi hoan nghênh những đóng góp về năng lực:
- Bắt đầu với một vấn đề. Mở một yêu cầu về khả năng để chúng ta có thể thảo luận về cách tiếp cận và mức độ ưu tiên trước khi viết mã.
- Sau đó mở PR và liên kết vấn đề. Chúng tôi xem xét dựa trên sự quan tâm của cộng đồng; số phiếu ủng hộ cả hai đều được tính.
- Đừng theo đuổi CI xanh. Hãy áp dụng phương pháp này và cho chúng tôi biết; chúng tôi có thể liên hệ với chi nhánh của bạn hoặc theo dõi và bạn sẽ được ghi nhận là tác giả gốc. (Xem Hướng dẫn đóng góp Pydantic AI)
Lưu ý: PR sửa đổi
pyproject.tomlhoặcuv.locktừ các thành viên không thuộc nhóm được CI tự động đóng để ngăn ngừa rủi ro chuỗi cung ứng. Nếu bạn cần một phần phụ thuộc mới, mở một vấn đề.
Phát triển
make install # install dependencies
make format # ruff format
make lint # ruff check
make typecheck # pyright strict
make test # pytest
make testcov # pytest with 100% branch coverage
Chính sách phiên bản
Pydantic AI Harness sử dụng phiên bản 0.x và đó là tuyên bố về độ ổn định của API, chứ không phải mức độ trưởng thành: các khả năng này được kiểm tra từ đầu đến cuối và được sử dụng trong sản xuất nhưng API của chúng vẫn có thể di chuyển giữa các bản phát hành nhỏ (0,1 -> 0,2): các tham số được đổi tên, mặc định đã thay đổi, các API được cơ cấu lại, luôn có cảnh báo không dùng nữa nếu thực tế. Các bản phát hành bản vá sẽ không cố ý phá vỡ hành vi hiện có và mọi thay đổi vi phạm đều được ghi lại trong ghi chú phát hành kèm theo hướng dẫn di chuyển mà agent của bạn có thể làm theo. Giữ harness ở một gói riêng biệt với Pydantic AI, có chính sách phiên bản chặt chẽ hơn, là thứ cho phép các khả năng lặp lại với tốc độ mà trường di chuyển.
Một phần của ngăn xếp Pydantic
Mọi thứ bạn cần để vận chuyển các AI agent cấp sản xuất:
- Pydantic AI: khung agent an toàn loại
- Pydantic Logfire: Ưu tiên AI, khả năng quan sát toàn bộ ngăn xếp
- Cổng AI Logfire: proxy LLM thống nhất
- Pydantic Evals: đánh giá bất kỳ hàm Python nào, bao gồm các agent
- genai-prices: dữ liệu giá mô hình, được cập nhật
Giấy phép
MIT; xem GIẤY PHÉP.