Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/acpremote/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ If you only need the shortest high-signal path:
- bearer-token protection
- transport latency metadata/projection
- host-ownership policy for mirrored clients
- explicit ACP unstable-protocol opt-in for elicitation routes

It does not own:

Expand Down
49 changes: 44 additions & 5 deletions .agents/skills/pydantic-acp/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: "pydantic-acp"
description: "Use for `pydantic-acp` tasks: exposing `pydantic_ai.Agent` through ACP, adapter config/runtime ownership, prompt capabilities, slash commands, approvals, plans, hooks, projections, host-backed tools, and Pydantic-specific examples."
description: "Use for `pydantic-acp` tasks: exposing `pydantic_ai.Agent` through ACP, adapter config/runtime ownership, extension routing, authentication, prompt capabilities, slash commands, approvals, plans, hooks, projections, host-backed tools, and Pydantic-specific examples."
---

# pydantic-acp Skill
Expand All @@ -24,6 +24,9 @@ In this package that rule affects:
- hook visibility
- external hook event projection
- custom slash commands
- custom ACP extension methods and notifications
- authentication method advertisement and execution
- typed, capability-gated choice elicitation
- session replay

## Start Here
Expand All @@ -46,6 +49,8 @@ If you only need the shortest high-signal path:
| hook visibility or external hook projection | Yes | [hooks bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py), [external hooks bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/external_hooks.py), [hook-introspection runtime](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py), [hook projection module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/hook_projection.py) |
| slash commands / model / mode surface | Yes | [custom slash command module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/slash.py), [slash-commands runtime](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py), [adapter-prompt runtime](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py), [providers module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/providers.py) |
| prompt capabilities or multimodal input flags | Yes | [prompt capabilities module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/prompt_capabilities.py), [adapter config module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/config.py), [prompt/resources docs](https://github.com/vcoderun/acpkit/blob/main/docs/pydantic-acp/prompt-resources.md) |
| private ACP methods, notifications, or authentication | Yes | [extensions module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/extensions.py), [runtime adapter](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py), [extensions/auth guide](https://github.com/vcoderun/acpkit/blob/main/docs/pydantic-acp/extensions-and-authentication.md) |
| typed user choices or low-level ACP elicitation | Yes | [elicitation module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/elicitation.py), [session-state module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py), [elicitation guide](https://github.com/vcoderun/acpkit/blob/main/docs/pydantic-acp/elicitation.md) |
| filesystem search/list projection or tool classification | Yes | [projection module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py), [host backends docs](https://github.com/vcoderun/acpkit/blob/main/docs/host-backends.md), [projection cookbook](https://github.com/vcoderun/acpkit/blob/main/docs/projection-cookbook.md) |
| Codex auth refresh or `auth.json` | No, pair with `codex-auth-helper` | [Codex helper package](https://github.com/vcoderun/acpkit/tree/main/packages/helpers/codex-auth-helper) |
| remote hosting or WebSocket transport | No, pair with `acpremote` | [remote transport package](https://github.com/vcoderun/acpkit/tree/main/packages/transports/acpremote) |
Expand All @@ -63,6 +68,7 @@ It owns:
- hook introspection and hook projection
- external hook event buffering
- custom slash command discovery and handling
- typed extension routing and authentication strategies
- host-backed filesystem and terminal ownership
- tool projection maps
- session store semantics and transcript replay
Expand Down Expand Up @@ -93,6 +99,7 @@ Package references:
- [Raw runtime controls docs](https://raw.githubusercontent.com/vcoderun/acpkit/main/docs/pydantic-acp/runtime-controls.md)
- [Raw plans, thinking, and approvals docs](https://raw.githubusercontent.com/vcoderun/acpkit/main/docs/pydantic-acp/plans-thinking-approvals.md)
- [Raw prompt/resources docs](https://raw.githubusercontent.com/vcoderun/acpkit/main/docs/pydantic-acp/prompt-resources.md)
- [Raw extensions/authentication docs](https://raw.githubusercontent.com/vcoderun/acpkit/main/docs/pydantic-acp/extensions-and-authentication.md)
- [Raw API docs](https://raw.githubusercontent.com/vcoderun/acpkit/main/docs/api/pydantic_acp.md)
- [Rendered overview](https://vcoderun.github.io/acpkit/pydantic-acp/)
- [Source tree](https://github.com/vcoderun/acpkit/tree/main/packages/adapters/pydantic-acp)
Expand All @@ -117,6 +124,12 @@ High-value public seams:
- `MemorySessionStore`
- `FileSessionStore`
- `AdapterPromptCapabilities`
- `ExtensionRouter`
- `AuthenticationProvider`
- `AuthenticationMethod`
- `ElicitationChoice`
- `ChoiceElicitationResult`
- `ElicitationUnsupportedError`
- `NativeApprovalBridge`
- `PermissionToolCallBuilder`
- `ApprovalPolicyStore`
Expand All @@ -141,7 +154,7 @@ Package entrypoint:

## Current Pydantic AI Compatibility

`pydantic-acp` supports `pydantic-ai-slim>=2.9.0,<=2.16.0`. Do not restore
`pydantic-acp` supports `pydantic-ai-slim>=2.9.0,<=2.23.0`. Do not restore
Pydantic AI V1 or pre-2.9.0 compatibility, or widen the upper bound without running the
runtime and type-check matrix:

Expand All @@ -162,16 +175,18 @@ When working on this surface, remember:
- keep the direct async-iterable fallback only for tests and compatibility fakes
- `OpenAICompactionBridge` must not pass deprecated `instructions=` into upstream `OpenAICompaction`
- Harness filesystem, shell, and CodeMode bridges are regression-tested against
`pydantic-ai-harness[code-mode]==0.10.0` through its public imports; do not
`pydantic-ai-harness[code-mode]==0.15.0` through its public imports; do not
duplicate unrelated Harness capabilities such as Memory or Guardrails in ACP Kit.
- Harness 0.10.0 requires `pydantic-ai-slim>=2.14.1`; use core adapter tests for
2.9.0 through 2.14.0 and run Harness capability tests on a compatible version.
- Harness 0.15.0 requires a compatible Pydantic AI release; keep Harness
capability tests on the locked development version and use the core adapter
matrix for the full supported range.

## Module Guide

| Subsystem | Key files | Use them for |
| --- | --- | --- |
| public surface and construction | [package entrypoint](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py), [adapter config module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/config.py), [prompt capabilities module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/prompt_capabilities.py), [agent source module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py), [agent type definitions](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/agent_types.py), [models module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/models.py), [providers module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/providers.py) | public API shape, construction seams, prompt capability flags, provider contracts |
| protocol extensions and authentication | [extensions module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/extensions.py), [runtime adapter](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py) | custom method and notification routing, auth advertisement, authentication execution |
| approvals | [approvals module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py), [approval store module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/approval_store.py), [permission presentation module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/permission_presentation.py), [prompt-execution runtime](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_execution.py), [prompt runtime](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py) | deferred approvals, remembered policy, permission cards, projection-aware approval context |
| bridges | [base bridge module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py), [capability-support bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/capability_support.py), [external hooks bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/external_hooks.py), [history-processor bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py), [hooks bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py), [MCP bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/mcp.py), [prepare-tools bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py), [thinking bridge](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py) | optional capability wiring, external event projection, and extension seams |
| projection | [projection module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py), [projection helper module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/projection_helpers.py), [projection text helpers](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py), [projection risk helpers](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_risk.py), [hook projection module](https://github.com/vcoderun/acpkit/blob/main/packages/adapters/pydantic-acp/src/pydantic_acp/hook_projection.py) | ACP-visible transcript cards and rendering |
Expand Down Expand Up @@ -280,6 +295,24 @@ Important rule:

Split those concerns before editing.

## Extensions And Authentication

- `ExtensionRouter` is for application-owned ACP JSON-RPC methods and
notifications that have no focused adapter mapping.
- `AuthenticationProvider` contributes `AuthenticationMethod` values during
initialization and handles `authenticate()`.
- Router-raised `RequestError` values must pass through unchanged.
- The adapter filters `TerminalAuthMethod` unless the client advertises
`auth.terminal=True`.
- Neither strategy receives private adapter runtime objects. Inject
application-owned collaborators directly.
- Do not turn `CapabilityBridge` into generic request middleware and do not use
`ExtensionRouter` to replace plans, providers, approvals, projections, or
host backends.

Use native `acp.interfaces.Agent` passthrough when most lifecycle behavior is
custom ACP rather than a Pydantic AI runtime projection.

## Host Ownership

This package has the repo's strongest host-side ownership model.
Expand Down Expand Up @@ -455,13 +488,19 @@ Stay in this skill when the main issue is:
- host policy
- projection
- session lifecycle
- extension routing or adapter authentication

## Guardrails

### ACP 0.11 Protocol Rules

- Depend on `agent-client-protocol==0.11.0`; do not reintroduce `ModelInfo` or
wire-level `session/set_model` calls.
- Preserve the no-provider defaults: no advertised auth methods, no-op
`authenticate`, ignored extension notifications, and `method_not_found` for
extension methods.
- Do not catch and rewrite `RequestError` from extension routers or
authentication providers.
- Model selection travels through `session/set_config_option` with
`config_id="model"`. `AcpProvider.model()` leaves the remote default intact;
an explicit provider model requires the remote agent to expose that select
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
name: Publish Packages

on:
push:
tags:
- "v[0-9]*"
release:
types: [published]

permissions:
contents: read
id-token: write

concurrency:
group: publish-${{ github.workflow }}-${{ github.ref }}
group: publish-${{ github.workflow }}-${{ github.event.release.tag_name }}
cancel-in-progress: false

jobs:
publish:
name: Build And Publish Workspace
runs-on: ubuntu-latest
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
steps:
- name: Check Out Repository
uses: actions/checkout@v7
with:
ref: ${{ github.event.release.tag_name }}

- name: Set Up Python
uses: actions/setup-python@v7
Expand All @@ -34,12 +37,12 @@ jobs:
- name: Validate, Build, And Smoke Test Release
run: |
uv sync --frozen --all-extras
make release RELEASE_TAG="${GITHUB_REF_NAME}"
make release RELEASE_TAG="$RELEASE_TAG"

- name: Upload Validated Release Artifacts
uses: actions/upload-artifact@v7
with:
name: acpkit-${{ github.ref_name }}
name: acpkit-${{ github.event.release.tag_name }}
path: dist/*
if-no-files-found: error
retention-days: 14
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
pydantic-ai-version: ["2.9.0", "2.9.1", "2.10.0", "2.11.0", "2.12.0", "2.13.0", "2.14.0", "2.14.1", "2.15.0", "2.16.0", "2.17.0", "2.18.0", "2.19.0", "2.20.0", "2.21.0", "2.22.0"]
pydantic-ai-version: ["2.9.0", "2.9.1", "2.10.0", "2.11.0", "2.12.0", "2.13.0", "2.14.0", "2.14.1", "2.15.0", "2.16.0", "2.17.0", "2.18.0", "2.19.0", "2.20.0", "2.21.0", "2.22.0", "2.23.0"]

steps:
- uses: actions/checkout@v7
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ ACP Kit uses synchronized versions for `acpkit`, `pydantic-acp`, `langchain-acp`

## [Unreleased]

## [1.6.0] - 2026-08-05

### Added

- `pydantic-acp` now exposes typed `ExtensionRouter` and
`AuthenticationProvider` strategies through `AdapterConfig`, allowing custom
ACP methods, notifications, and authentication without subclassing the
adapter. Defaults remain backward compatible, structured `RequestError`
values pass through unchanged, and ACP 0.11 terminal auth methods are
advertised only to capable clients.
- `AcpSessionContext.ask_choice()` compiles typed single-choice values to ACP
form elicitation, returns distinct accepted, declined, and cancelled results,
validates accepted client responses, and supports an explicit sync or async
fallback for clients without form elicitation.
- `acpremote.TransportOptions.use_unstable_protocol` forwards the ACP SDK opt-in
required by ACP 0.11 elicitation routes on object-based client and server
connections.

### Changed

- `pydantic-acp` now supports `pydantic-ai-slim>=2.9.0,<=2.23.0`; runtime,
type-check, and CI compatibility matrices include 2.23.0.

## [1.5.2] - 2026-08-01

### Changed
Expand Down
4 changes: 2 additions & 2 deletions COVERAGE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Line coverage: 100.00% (10403 / 10403)
Branch coverage: 100.00% (3458 / 3458)
Line coverage: 100.00% (10519 / 10519)
Branch coverage: 100.00% (3496 / 3496)
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ BLUE := \033[1;34m
GREEN := \033[1;32m
RESET := \033[0m
PYTHON_VERSIONS := 3.11.13 3.12.10 3.13.9
PYDANTIC_AI_VERSIONS := 2.9.0 2.9.1 2.10.0 2.11.0 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.16.0 2.17.0 2.18.0 2.19.0 2.20.0 2.21.0 2.22.0
PYDANTIC_AI_VERSIONS := 2.9.0 2.9.1 2.10.0 2.11.0 2.12.0 2.13.0 2.14.0 2.14.1 2.15.0 2.16.0 2.17.0 2.18.0 2.19.0 2.20.0 2.21.0 2.22.0 2.23.0
LANGCHAIN_VERSION := 1.3.11
LANGGRAPH_VERSION := 1.2.7
DEEPAGENTS_VERSION := 0.6.12
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.5.2
1.6.0
6 changes: 6 additions & 0 deletions docs/acpremote.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ agent = connect_acp(

## Typical End-To-End Flows

ACP 0.11 keeps elicitation routes behind the SDK's unstable-protocol flag. For
ACP agents that call `create_elicitation()` or `ask_choice()`, pass
`TransportOptions(use_unstable_protocol=True)` to both `serve_acp()` and
`connect_remote_agent()`. Command relays forward frames unchanged, so the
spawned stdio ACP command must also enable unstable protocol routes.

Remote-host flow:

```bash
Expand Down
24 changes: 24 additions & 0 deletions docs/api/pydantic_acp.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ This page documents the public surface re-exported by `pydantic_acp`.

::: pydantic_acp.RuntimeAgent

## Typed Elicitation

::: pydantic_acp.ElicitationChoice

::: pydantic_acp.ChoiceElicitationResult

::: pydantic_acp.ChoiceElicitationAccepted

::: pydantic_acp.ChoiceElicitationDeclined

::: pydantic_acp.ChoiceElicitationCancelled

::: pydantic_acp.ElicitationUnsupportedError

::: pydantic_acp.InvalidElicitationResponseError

## Protocol Extension And Authentication Contracts

::: pydantic_acp.ExtensionRouter

::: pydantic_acp.AuthenticationProvider

::: pydantic_acp.AuthenticationMethod

## ACP Client Provider Bridge

::: pydantic_acp.AcpProvider
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ uv add pydantic-acp
pip install pydantic-acp
```

`pydantic-acp` supports `pydantic-ai-slim>=2.9.0,<=2.22.0` and pins the ACP
`pydantic-acp` supports `pydantic-ai-slim>=2.9.0,<=2.23.0` and pins the ACP
protocol version it integrates against. Pydantic AI V1 and releases before
2.9.0 are not supported.

Expand Down
Loading