acpkit 0.4.2__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acpkit-0.6.0/.agents/skills/acpkit-sdk/SKILL.md +505 -0
- acpkit-0.6.0/.agents/skills/acpkit-sdk/agents/openai.yaml +7 -0
- acpkit-0.6.0/.agents/skills/acpkit-sdk/resources/intro.md +79 -0
- acpkit-0.6.0/.agents/skills/acpkit-sdk/scripts/list_examples.py +32 -0
- acpkit-0.6.0/.agents/skills/acpkit-sdk/scripts/list_public_exports.py +52 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/workflows/docs.yml +2 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/workflows/test.yml +2 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/.gitignore +8 -4
- acpkit-0.6.0/.pre-commit-config.yaml +38 -0
- acpkit-0.6.0/COVERAGE +2 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/Makefile +29 -3
- {acpkit-0.4.2 → acpkit-0.6.0}/PKG-INFO +69 -40
- {acpkit-0.4.2 → acpkit-0.6.0}/README.md +67 -38
- acpkit-0.6.0/VERSION +1 -0
- acpkit-0.6.0/docs/.partials/index-header.html +13 -0
- acpkit-0.6.0/docs/about/index.md +46 -0
- acpkit-0.6.0/docs/api/acpkit.md +25 -0
- acpkit-0.6.0/docs/api/codex_auth_helper.md +23 -0
- acpkit-0.6.0/docs/api/pydantic_acp.md +101 -0
- acpkit-0.6.0/docs/bridges.md +346 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/docs/cli.md +34 -35
- acpkit-0.6.0/docs/examples/factory.md +47 -0
- acpkit-0.6.0/docs/examples/index.md +43 -0
- acpkit-0.6.0/docs/examples/minimal.md +42 -0
- acpkit-0.6.0/docs/examples/providers.md +33 -0
- acpkit-0.6.0/docs/examples/workspace-agent.md +277 -0
- acpkit-0.6.0/docs/getting-started/installation.md +105 -0
- acpkit-0.6.0/docs/getting-started/quickstart.md +203 -0
- acpkit-0.6.0/docs/helpers.md +72 -0
- acpkit-0.6.0/docs/host-backends.md +109 -0
- acpkit-0.6.0/docs/index.md +110 -0
- acpkit-0.6.0/docs/llms-full.txt +3021 -0
- acpkit-0.6.0/docs/llms.txt +95 -0
- acpkit-0.6.0/docs/providers.md +266 -0
- acpkit-0.6.0/docs/pydantic-acp/adapter-config.md +197 -0
- acpkit-0.6.0/docs/pydantic-acp/plans-thinking-approvals.md +156 -0
- acpkit-0.6.0/docs/pydantic-acp/runtime-controls.md +190 -0
- acpkit-0.6.0/docs/pydantic-acp/session-state.md +149 -0
- acpkit-0.6.0/docs/pydantic-acp.md +225 -0
- acpkit-0.6.0/docs/stylesheets/tweaks.css +137 -0
- acpkit-0.6.0/docs/testing.md +118 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/strong_agent.py +162 -79
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/strong_agent_v2.py +145 -79
- acpkit-0.6.0/mkdocs.yml +105 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/README.md +18 -2
- acpkit-0.6.0/packages/adapters/pydantic-acp/VERSION +1 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/pyproject.toml +5 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py +23 -1
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py +54 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py +5 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py +4 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py +497 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py +13 -4
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py +11 -8
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py +66 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/mcp.py +2 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py +8 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py +118 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/builders/agent.py +7 -11
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/config.py +4 -1
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/hook_projection.py +4 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py +155 -106
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/providers.py +12 -1
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py +273 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py +159 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py +313 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_execution.py +369 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_model_runtime.py +157 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py +349 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py +137 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py +187 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py +609 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py +459 -0
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py +713 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/bridge_manager.py +15 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py +92 -6
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py +285 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py +115 -34
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/serialization.py +3 -3
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py +3 -3
- acpkit-0.6.0/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py +248 -0
- acpkit-0.6.0/packages/helpers/codex-auth-helper/LICENSE +201 -0
- acpkit-0.6.0/packages/helpers/codex-auth-helper/VERSION +1 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/pyproject.toml +5 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py +2 -0
- acpkit-0.6.0/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py +5 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py +3 -3
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py +10 -8
- {acpkit-0.4.2 → acpkit-0.6.0}/pyproject.toml +11 -9
- {acpkit-0.4.2 → acpkit-0.6.0}/pyrightconfig.json +2 -0
- acpkit-0.6.0/scripts/check_pypi_versions.py +159 -0
- acpkit-0.6.0/scripts/generate_llms_docs.py +284 -0
- acpkit-0.6.0/scripts/run_if_major_change.py +122 -0
- acpkit-0.6.0/scripts/save_coverage_summary.py +136 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/__init__.py +1 -2
- acpkit-0.6.0/src/acpkit/_version.py +5 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/adapters.py +7 -7
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/runtime.py +6 -6
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/codex_auth_helper/support.py +7 -3
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/codex_auth_helper/test_factory.py +7 -4
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/conftest.py +2 -2
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/support.py +3 -1
- acpkit-0.6.0/tests/pydantic/test_adapter_helpers.py +1039 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_approvals.py +110 -0
- acpkit-0.4.2/tests/pydantic/test_bridges.py → acpkit-0.6.0/tests/pydantic/test_bridge_builder.py +2 -160
- acpkit-0.6.0/tests/pydantic/test_bridge_hooks.py +589 -0
- acpkit-0.6.0/tests/pydantic/test_bridge_mcp.py +361 -0
- acpkit-0.6.0/tests/pydantic/test_bridge_prepare_tools.py +101 -0
- acpkit-0.6.0/tests/pydantic/test_bridge_thinking.py +135 -0
- acpkit-0.6.0/tests/pydantic/test_hook_introspection.py +455 -0
- acpkit-0.6.0/tests/pydantic/test_low_level_helpers.py +1136 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_models.py +158 -12
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_runtime.py +178 -0
- acpkit-0.6.0/tests/pydantic/test_slash_commands.py +827 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/test_acpkit_cli.py +39 -4
- acpkit-0.4.2/.pre-commit-config.yaml +0 -14
- acpkit-0.4.2/SKILL.md +0 -723
- acpkit-0.4.2/VERSION +0 -1
- acpkit-0.4.2/docs/about/index.md +0 -26
- acpkit-0.4.2/docs/bridges.md +0 -140
- acpkit-0.4.2/docs/helpers.md +0 -46
- acpkit-0.4.2/docs/host-backends.md +0 -53
- acpkit-0.4.2/docs/index.md +0 -77
- acpkit-0.4.2/docs/llms.txt +0 -37
- acpkit-0.4.2/docs/providers.md +0 -281
- acpkit-0.4.2/docs/testing.md +0 -48
- acpkit-0.4.2/mkdocs.yml +0 -18
- acpkit-0.4.2/packages/adapters/pydantic-acp/VERSION +0 -1
- acpkit-0.4.2/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py +0 -478
- acpkit-0.4.2/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py +0 -1617
- acpkit-0.4.2/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py +0 -123
- acpkit-0.4.2/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py +0 -165
- acpkit-0.4.2/packages/helpers/codex-auth-helper/LICENSE +0 -21
- acpkit-0.4.2/packages/helpers/codex-auth-helper/VERSION +0 -1
- acpkit-0.4.2/tests/pydantic/test_hook_introspection.py +0 -217
- acpkit-0.4.2/tests/pydantic/test_slash_commands.py +0 -291
- {acpkit-0.4.2 → acpkit-0.6.0}/.cursorrules +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.editorconfig +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/dependabot.yml +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/workflows/monorepo-ci.yml +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.github/workflows/publish.yml +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/.python-version +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/CODE_OF_CONDUCT.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/CONTRIBUTING.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/LICENSE +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/SECURITY.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/context7.json +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/.gitignore +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/README.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/approvals.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/bridges.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/factory_agent.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/hook_projection.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/host_context.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/providers.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/examples/pydantic/static_agent.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/agent_types.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/builders/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/context.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/filesystem.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/terminal.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/models.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/py.typed +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/session_surface.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/adapters/pydantic-acp/src/pydantic_acp/session/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/.gitignore +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/README.md +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/config.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/model.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/py.typed +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/scripts/demo_mcp_server.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/scripts/mock_hook_audit.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/scripts/mock_hook_snapshot.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/__main__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/cli.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/src/acpkit/py.typed +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/codex_auth_helper/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/__init__.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_host.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_projection.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/pydantic/test_sources.py +0 -0
- {acpkit-0.4.2 → acpkit-0.6.0}/tests/test_native_pydantic_agent.py +0 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: acpkit-sdk
|
|
3
|
+
description: Use for ACP Kit SDK tasks that turn an existing agent surface into a truthful ACP server through acpkit, pydantic-acp, the published docs, and the maintained examples.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ACP Kit SDK
|
|
7
|
+
|
|
8
|
+
ACP Kit is the adapter toolkit and monorepo for turning an existing agent surface into a truthful ACP server boundary.
|
|
9
|
+
|
|
10
|
+
Today the stable production focus is `pydantic-acp`: exposing `pydantic_ai.Agent` through ACP
|
|
11
|
+
while keeping models, modes, plans, approvals, MCP metadata, host tools, and session state
|
|
12
|
+
aligned with what the underlying runtime can actually support.
|
|
13
|
+
|
|
14
|
+
Additional adapters such as `langchain-acp` and `dspy-acp` are planned after `pydantic-acp`
|
|
15
|
+
reaches 1.0 stability.
|
|
16
|
+
|
|
17
|
+
This skill file is the longform, high-context entrypoint for the packaged `acpkit-sdk` skill and
|
|
18
|
+
should be treated as the primary skill surface when the skill is selected.
|
|
19
|
+
|
|
20
|
+
When you need the docs map or the full docs corpus in one place, read [llms.txt](https://vcoderun.github.io/acpkit/llms.txt) or [llms-full.txt](https://vcoderun.github.io/acpkit/llms-full.txt).
|
|
21
|
+
|
|
22
|
+
## What ACP Kit Ships
|
|
23
|
+
|
|
24
|
+
ACP Kit currently has three main Python packages:
|
|
25
|
+
|
|
26
|
+
| Package | Role | Typical use |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `acpkit` | root CLI and target resolver | `acpkit run ...`, `acpkit launch ...`, target loading |
|
|
29
|
+
| `pydantic-acp` | ACP adapter for `pydantic_ai.Agent` | expose an existing agent through ACP without rewriting it |
|
|
30
|
+
| `codex-auth-helper` | Codex-backed Pydantic AI helper | build Codex-backed Responses models from a local Codex login |
|
|
31
|
+
|
|
32
|
+
The core contract across the repo is:
|
|
33
|
+
|
|
34
|
+
> expose ACP state only when the underlying runtime can actually honor it.
|
|
35
|
+
|
|
36
|
+
That rule affects model selection, mode switching, slash commands, native plan state, approval
|
|
37
|
+
flow, MCP metadata, hook rendering, cancellation, and host-backed tooling.
|
|
38
|
+
|
|
39
|
+
## Use The Right Construction Seam
|
|
40
|
+
|
|
41
|
+
Pick the narrowest seam that matches the job:
|
|
42
|
+
|
|
43
|
+
| Seam | Use it when |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `run_acp(agent=...)` | you want the smallest direct path from `pydantic_ai.Agent` to a running ACP server |
|
|
46
|
+
| `create_acp_agent(...)` | you need the ACP-compatible agent object before running it |
|
|
47
|
+
| `agent_factory=` | the current session should influence agent construction, but a full custom source is unnecessary |
|
|
48
|
+
| `agent_source=` | you need full control over the agent build path, host binding, and session-specific dependencies |
|
|
49
|
+
| built-in `AdapterConfig` fields | the adapter can own the relevant runtime state cleanly |
|
|
50
|
+
| providers | the host or product layer should remain the source of truth |
|
|
51
|
+
| bridges | the runtime needs ACP-visible capabilities without hard-coding them into the adapter core |
|
|
52
|
+
|
|
53
|
+
## CLI And Target Resolution
|
|
54
|
+
|
|
55
|
+
The root `acpkit` package resolves Python targets and dispatches them to the matching adapter.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
acpkit run my_agent
|
|
59
|
+
acpkit run my_agent:agent
|
|
60
|
+
acpkit run app.agents.demo:agent -p ./examples
|
|
61
|
+
acpkit launch my_agent:agent -p ./examples
|
|
62
|
+
acpkit launch --command "python3.11 strong_agent.py"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Target resolution behavior:
|
|
66
|
+
|
|
67
|
+
1. add the current working directory to `sys.path`
|
|
68
|
+
2. add any `-p/--path` roots
|
|
69
|
+
3. import the requested module
|
|
70
|
+
4. if `module:attribute` was given, resolve the attribute path
|
|
71
|
+
5. if only `module` was given, select the last defined `pydantic_ai.Agent` in that module
|
|
72
|
+
|
|
73
|
+
Current built-in auto-dispatch support is centered on `pydantic_ai.Agent`.
|
|
74
|
+
|
|
75
|
+
## Smallest Adapter Path: `run_acp(...)`
|
|
76
|
+
|
|
77
|
+
Use `run_acp(...)` when one existing agent instance is enough.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from pydantic_ai import Agent
|
|
81
|
+
from pydantic_acp import run_acp
|
|
82
|
+
|
|
83
|
+
agent = Agent(
|
|
84
|
+
'openai:gpt-5',
|
|
85
|
+
name='weather-agent',
|
|
86
|
+
instructions='Answer briefly and ask for clarification when location is missing.',
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@agent.tool_plain
|
|
91
|
+
def lookup_weather(city: str) -> str:
|
|
92
|
+
"""Return a canned weather response for demos."""
|
|
93
|
+
|
|
94
|
+
return f'Weather in {city}: sunny'
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
run_acp(agent=agent)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This is the narrowest path from an existing agent surface to a live ACP server.
|
|
101
|
+
|
|
102
|
+
## ACP Agent Without Running: `create_acp_agent(...)`
|
|
103
|
+
|
|
104
|
+
Use `create_acp_agent(...)` when you need the ACP-compatible agent object first.
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from acp import run_agent
|
|
108
|
+
from pydantic_ai import Agent
|
|
109
|
+
from pydantic_acp import AdapterConfig, MemorySessionStore, create_acp_agent
|
|
110
|
+
|
|
111
|
+
agent = Agent('openai:gpt-5', name='composable-agent')
|
|
112
|
+
|
|
113
|
+
acp_agent = create_acp_agent(
|
|
114
|
+
agent=agent,
|
|
115
|
+
config=AdapterConfig(
|
|
116
|
+
agent_name='my-service',
|
|
117
|
+
agent_title='My Service Agent',
|
|
118
|
+
session_store=MemorySessionStore(),
|
|
119
|
+
),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# later:
|
|
123
|
+
# await run_agent(acp_agent)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Use this seam when ACP is only one part of a larger async service boundary.
|
|
127
|
+
|
|
128
|
+
## `AdapterConfig` Is The Main Runtime Surface
|
|
129
|
+
|
|
130
|
+
`AdapterConfig` is where the adapter’s built-in ownership lives:
|
|
131
|
+
|
|
132
|
+
- session storage
|
|
133
|
+
- model selection
|
|
134
|
+
- approval bridging
|
|
135
|
+
- capability bridges
|
|
136
|
+
- plan persistence callbacks
|
|
137
|
+
- hook projection and runtime shaping
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from pathlib import Path
|
|
141
|
+
|
|
142
|
+
from pydantic_ai import Agent
|
|
143
|
+
from pydantic_acp import (
|
|
144
|
+
AdapterConfig,
|
|
145
|
+
AdapterModel,
|
|
146
|
+
FileSessionStore,
|
|
147
|
+
NativeApprovalBridge,
|
|
148
|
+
ThinkingBridge,
|
|
149
|
+
run_acp,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
agent = Agent('openai:gpt-5', name='configured-agent')
|
|
153
|
+
|
|
154
|
+
config = AdapterConfig(
|
|
155
|
+
agent_name='my-agent',
|
|
156
|
+
agent_title='My Agent Title',
|
|
157
|
+
allow_model_selection=True,
|
|
158
|
+
available_models=[
|
|
159
|
+
AdapterModel(
|
|
160
|
+
model_id='fast',
|
|
161
|
+
name='Fast',
|
|
162
|
+
description='Lower-latency responses.',
|
|
163
|
+
override='openai:gpt-5-mini',
|
|
164
|
+
),
|
|
165
|
+
AdapterModel(
|
|
166
|
+
model_id='smart',
|
|
167
|
+
name='Smart',
|
|
168
|
+
description='Higher-quality responses.',
|
|
169
|
+
override='openai:gpt-5',
|
|
170
|
+
),
|
|
171
|
+
],
|
|
172
|
+
capability_bridges=[ThinkingBridge()],
|
|
173
|
+
approval_bridge=NativeApprovalBridge(enable_persistent_choices=True),
|
|
174
|
+
session_store=FileSessionStore(root=Path('.acp-sessions')),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
run_acp(agent=agent, config=config)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
High-value detail:
|
|
181
|
+
|
|
182
|
+
- `FileSessionStore` takes `root=Path(...)`, not `base_dir=...`
|
|
183
|
+
|
|
184
|
+
## Session Stores
|
|
185
|
+
|
|
186
|
+
ACP Kit currently ships two session stores:
|
|
187
|
+
|
|
188
|
+
- `MemorySessionStore`
|
|
189
|
+
- `FileSessionStore`
|
|
190
|
+
|
|
191
|
+
`MemorySessionStore` is ephemeral. `FileSessionStore` persists ACP sessions across restarts and
|
|
192
|
+
supports:
|
|
193
|
+
|
|
194
|
+
- save
|
|
195
|
+
- get
|
|
196
|
+
- list
|
|
197
|
+
- fork
|
|
198
|
+
- delete
|
|
199
|
+
|
|
200
|
+
Use `FileSessionStore(root=Path(...))` when real ACP clients need durable session state.
|
|
201
|
+
|
|
202
|
+
Current `FileSessionStore` behavior is tuned for durable local-host ACP use:
|
|
203
|
+
|
|
204
|
+
- atomic temp-file write plus replace
|
|
205
|
+
- local process lock and filesystem advisory lock when available
|
|
206
|
+
- malformed saved session files are skipped in public load/list flows
|
|
207
|
+
- stale temp files are cleaned up on startup
|
|
208
|
+
|
|
209
|
+
It is a strong default for editors and single-host services, not a distributed shared-state backend.
|
|
210
|
+
|
|
211
|
+
## Agent Factories And `AgentSource`
|
|
212
|
+
|
|
213
|
+
Use an agent factory when session context changes agent construction but you do not need a full
|
|
214
|
+
custom source object.
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from pydantic_ai import Agent
|
|
218
|
+
from pydantic_acp import AcpSessionContext, AdapterConfig, run_acp
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def build_agent(session: AcpSessionContext) -> Agent[None, str]:
|
|
222
|
+
workspace_name = session.cwd.name
|
|
223
|
+
return Agent(
|
|
224
|
+
'openai:gpt-5',
|
|
225
|
+
name=f'agent-{workspace_name}',
|
|
226
|
+
instructions=f'You are working in {workspace_name}.',
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
run_acp(
|
|
231
|
+
agent_factory=build_agent,
|
|
232
|
+
config=AdapterConfig(agent_name='factory-agent'),
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Use `AgentSource` when you need full control over both the agent and the dependency object:
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from dataclasses import dataclass
|
|
240
|
+
|
|
241
|
+
from pydantic_ai import Agent
|
|
242
|
+
from pydantic_acp import AcpSessionContext, AgentSource, AdapterConfig, run_acp
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@dataclass(frozen=True, slots=True)
|
|
246
|
+
class Deps:
|
|
247
|
+
workspace_name: str
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class WorkspaceSource(AgentSource[Deps]):
|
|
251
|
+
async def get_agent(self, session: AcpSessionContext) -> Agent[Deps, str]:
|
|
252
|
+
return Agent(
|
|
253
|
+
'openai:gpt-5',
|
|
254
|
+
name='workspace-agent',
|
|
255
|
+
instructions='Use the provided workspace dependencies.',
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
async def get_deps(self, session: AcpSessionContext) -> Deps:
|
|
259
|
+
return Deps(workspace_name=session.cwd.name)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
run_acp(
|
|
263
|
+
agent_source=WorkspaceSource(),
|
|
264
|
+
config=AdapterConfig(agent_name='workspace-agent'),
|
|
265
|
+
)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Reach for `AgentSource` in production-style examples where:
|
|
269
|
+
|
|
270
|
+
- session cwd matters
|
|
271
|
+
- model ids or modes come from the host
|
|
272
|
+
- tools depend on host-backed services
|
|
273
|
+
- you need a richer dependency object than the adapter can infer on its own
|
|
274
|
+
|
|
275
|
+
## Models, Modes, And Slash Commands
|
|
276
|
+
|
|
277
|
+
ACP Kit can expose session-local model and mode switching through two different ownership paths.
|
|
278
|
+
|
|
279
|
+
### Built-in model selection
|
|
280
|
+
|
|
281
|
+
Use built-in model selection when the adapter can own the available model set:
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from pydantic_acp import AdapterConfig, AdapterModel
|
|
285
|
+
|
|
286
|
+
config = AdapterConfig(
|
|
287
|
+
allow_model_selection=True,
|
|
288
|
+
available_models=[
|
|
289
|
+
AdapterModel(
|
|
290
|
+
model_id='fast',
|
|
291
|
+
name='Fast',
|
|
292
|
+
description='Lower latency.',
|
|
293
|
+
override='openai:gpt-5-mini',
|
|
294
|
+
),
|
|
295
|
+
AdapterModel(
|
|
296
|
+
model_id='smart',
|
|
297
|
+
name='Smart',
|
|
298
|
+
description='Higher quality.',
|
|
299
|
+
override='openai:gpt-5',
|
|
300
|
+
),
|
|
301
|
+
],
|
|
302
|
+
)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Provider-owned model or mode state
|
|
306
|
+
|
|
307
|
+
Use providers when the host already owns that state:
|
|
308
|
+
|
|
309
|
+
- `SessionModelsProvider`
|
|
310
|
+
- `SessionModesProvider`
|
|
311
|
+
- `ConfigOptionsProvider`
|
|
312
|
+
|
|
313
|
+
Mode slash commands are dynamic. They are derived from the configured mode ids rather than from a
|
|
314
|
+
hard-coded global set.
|
|
315
|
+
|
|
316
|
+
Important guardrail:
|
|
317
|
+
|
|
318
|
+
- mode ids must not collide with reserved slash-command names such as `model`, `thinking`,
|
|
319
|
+
`tools`, `hooks`, or `mcp-servers`
|
|
320
|
+
|
|
321
|
+
## Capability Bridges
|
|
322
|
+
|
|
323
|
+
Capability bridges are how ACP-visible runtime behavior gets added without hard-coding everything
|
|
324
|
+
into the adapter core.
|
|
325
|
+
|
|
326
|
+
Common bridges:
|
|
327
|
+
|
|
328
|
+
- `PrepareToolsBridge`
|
|
329
|
+
- `ThinkingBridge`
|
|
330
|
+
- `McpBridge`
|
|
331
|
+
- `HookBridge`
|
|
332
|
+
- `HistoryProcessorBridge`
|
|
333
|
+
|
|
334
|
+
Use `PrepareToolsBridge` to define dynamic modes and tool surfaces:
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
from pydantic_acp import PrepareToolsBridge, PrepareToolsMode
|
|
338
|
+
from pydantic_ai.tools import RunContext, ToolDefinition
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def ask_tools(
|
|
342
|
+
ctx: RunContext[None],
|
|
343
|
+
tool_defs: list[ToolDefinition],
|
|
344
|
+
) -> list[ToolDefinition]:
|
|
345
|
+
del ctx
|
|
346
|
+
return [tool_def for tool_def in tool_defs if not tool_def.name.startswith('write_')]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def agent_tools(
|
|
350
|
+
ctx: RunContext[None],
|
|
351
|
+
tool_defs: list[ToolDefinition],
|
|
352
|
+
) -> list[ToolDefinition]:
|
|
353
|
+
del ctx
|
|
354
|
+
return list(tool_defs)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
bridge = PrepareToolsBridge(
|
|
358
|
+
default_mode_id='ask',
|
|
359
|
+
modes=[
|
|
360
|
+
PrepareToolsMode(
|
|
361
|
+
id='ask',
|
|
362
|
+
name='Ask',
|
|
363
|
+
description='Read-only inspection mode.',
|
|
364
|
+
prepare_func=ask_tools,
|
|
365
|
+
),
|
|
366
|
+
PrepareToolsMode(
|
|
367
|
+
id='plan',
|
|
368
|
+
name='Plan',
|
|
369
|
+
description='Native ACP plan mode.',
|
|
370
|
+
prepare_func=ask_tools,
|
|
371
|
+
plan_mode=True,
|
|
372
|
+
),
|
|
373
|
+
PrepareToolsMode(
|
|
374
|
+
id='agent',
|
|
375
|
+
name='Agent',
|
|
376
|
+
description='Full tool surface.',
|
|
377
|
+
prepare_func=agent_tools,
|
|
378
|
+
plan_tools=True,
|
|
379
|
+
),
|
|
380
|
+
],
|
|
381
|
+
)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
High-value guardrails:
|
|
385
|
+
|
|
386
|
+
- only one `PrepareToolsMode(..., plan_mode=True)` is allowed
|
|
387
|
+
- `plan_tools=True` is how a non-plan execution mode keeps plan progress tools visible
|
|
388
|
+
- `ThinkingBridge()` is what makes `/thinking` and the ACP-visible effort selector exist
|
|
389
|
+
- `HookBridge(hide_all=True)` suppresses hook listing output without removing the hook seam itself
|
|
390
|
+
- custom `run_event_stream` hooks or wrappers must return an async iterable; returning a coroutine will break stream execution
|
|
391
|
+
|
|
392
|
+
## Plans, Approvals, Cancellation, And Host Tools
|
|
393
|
+
|
|
394
|
+
Native ACP plan state is separate from provider-owned plan state.
|
|
395
|
+
|
|
396
|
+
Use native plan state when you want the adapter to own the ACP-visible plan lifecycle. Use
|
|
397
|
+
`PlanProvider` when the host should remain the source of truth.
|
|
398
|
+
|
|
399
|
+
Current plan behavior to remember:
|
|
400
|
+
|
|
401
|
+
- `plan_mode=True` exposes native ACP plan creation tools
|
|
402
|
+
- `plan_tools=True` lets execution modes keep plan progress tools visible
|
|
403
|
+
- native plan persistence can be mirrored outward through `NativePlanPersistenceProvider`
|
|
404
|
+
|
|
405
|
+
Approval behavior:
|
|
406
|
+
|
|
407
|
+
- `NativeApprovalBridge` powers the live ACP approval flow
|
|
408
|
+
- `ApprovalStateProvider` exposes extra approval metadata when the host already owns approval state
|
|
409
|
+
|
|
410
|
+
Cancellation behavior:
|
|
411
|
+
|
|
412
|
+
- ACP cancellation is wired through the runtime now
|
|
413
|
+
- cancellation preserves session state and transcript integrity instead of leaving the session in a broken partial state
|
|
414
|
+
|
|
415
|
+
Host-backed tools:
|
|
416
|
+
|
|
417
|
+
- ACP Kit can expose client-backed filesystem and shell helpers
|
|
418
|
+
- projection maps change how tools are rendered in ACP clients without changing the underlying tool contract
|
|
419
|
+
|
|
420
|
+
## Projection Maps And Hook Rendering
|
|
421
|
+
|
|
422
|
+
Projection maps make ACP clients see richer file or command behavior than a raw generic tool card.
|
|
423
|
+
|
|
424
|
+
Common maps:
|
|
425
|
+
|
|
426
|
+
- filesystem maps
|
|
427
|
+
- bash / command maps
|
|
428
|
+
- hook projection maps
|
|
429
|
+
|
|
430
|
+
Use them when the client should see more structured output, but avoid pretending a tool is
|
|
431
|
+
something it is not.
|
|
432
|
+
|
|
433
|
+
## Examples That Matter
|
|
434
|
+
|
|
435
|
+
High-value maintained examples live under `examples/pydantic/`:
|
|
436
|
+
|
|
437
|
+
| Example | Purpose |
|
|
438
|
+
| --- | --- |
|
|
439
|
+
| [`examples/pydantic/acp_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/acp_agent.py) | smallest direct `run_acp(...)` path |
|
|
440
|
+
| [`examples/pydantic/factory_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/factory_agent.py) | session-aware factory |
|
|
441
|
+
| [`examples/pydantic/providers.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/providers.py) | host-owned models, modes, config, plan, and approval metadata |
|
|
442
|
+
| [`examples/pydantic/approvals.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/approvals.py) | deferred approval flow |
|
|
443
|
+
| [`examples/pydantic/bridges.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/bridges.py) | bridge builder and ACP-visible capabilities |
|
|
444
|
+
| [`examples/pydantic/host_context.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/host_context.py) | client-backed filesystem and terminal helpers |
|
|
445
|
+
| [`examples/pydantic/hook_projection.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/hook_projection.py) | hook rendering and `HookProjectionMap` behavior |
|
|
446
|
+
| [`examples/pydantic/strong_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent.py) | production-style workspace coding-agent showcase |
|
|
447
|
+
| [`examples/pydantic/strong_agent_v2.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent_v2.py) | alternative workspace integration shape |
|
|
448
|
+
|
|
449
|
+
Use [`strong_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent.py) when the docs or code need to highlight:
|
|
450
|
+
|
|
451
|
+
- mode-aware tool shaping
|
|
452
|
+
- provider-owned model and mode state
|
|
453
|
+
- native plan persistence
|
|
454
|
+
- host-backed tools
|
|
455
|
+
- MCP metadata mapping
|
|
456
|
+
- bridge composition
|
|
457
|
+
- projection maps
|
|
458
|
+
- final `create_acp_agent(...)` assembly
|
|
459
|
+
|
|
460
|
+
## Documentation Sources
|
|
461
|
+
|
|
462
|
+
High-value docs pages:
|
|
463
|
+
|
|
464
|
+
- [ACP Kit Overview](https://vcoderun.github.io/acpkit/)
|
|
465
|
+
- [Pydantic ACP Overview](https://vcoderun.github.io/acpkit/pydantic-acp/)
|
|
466
|
+
- [AdapterConfig](https://vcoderun.github.io/acpkit/pydantic-acp/adapter-config/)
|
|
467
|
+
- [Session State and Lifecycle](https://vcoderun.github.io/acpkit/pydantic-acp/session-state/)
|
|
468
|
+
- [Models, Modes, and Slash Commands](https://vcoderun.github.io/acpkit/pydantic-acp/runtime-controls/)
|
|
469
|
+
- [Plans, Thinking, and Approvals](https://vcoderun.github.io/acpkit/pydantic-acp/plans-thinking-approvals/)
|
|
470
|
+
- [Providers](https://vcoderun.github.io/acpkit/providers/)
|
|
471
|
+
- [Bridges](https://vcoderun.github.io/acpkit/bridges/)
|
|
472
|
+
- [Host Backends and Projections](https://vcoderun.github.io/acpkit/host-backends/)
|
|
473
|
+
- [Examples Overview](https://vcoderun.github.io/acpkit/examples/)
|
|
474
|
+
- [Workspace Agent](https://vcoderun.github.io/acpkit/examples/workspace-agent/)
|
|
475
|
+
- [pydantic_acp API](https://vcoderun.github.io/acpkit/api/pydantic_acp/)
|
|
476
|
+
|
|
477
|
+
## Skill-Local Routing Aids
|
|
478
|
+
|
|
479
|
+
These files exist to route you quickly into the right part of the codebase or docs set when the
|
|
480
|
+
task is narrow:
|
|
481
|
+
|
|
482
|
+
- [resources/intro.md](resources/intro.md)
|
|
483
|
+
- [references/package-surface.md](references/package-surface.md)
|
|
484
|
+
- [references/runtime-capabilities.md](references/runtime-capabilities.md)
|
|
485
|
+
- [references/docs-examples-map.md](references/docs-examples-map.md)
|
|
486
|
+
|
|
487
|
+
## Utility Scripts
|
|
488
|
+
|
|
489
|
+
Use the bundled scripts instead of guessing:
|
|
490
|
+
|
|
491
|
+
- `python3.11 .agents/skills/acpkit-sdk/scripts/list_public_exports.py`
|
|
492
|
+
- `python3.11 .agents/skills/acpkit-sdk/scripts/list_examples.py`
|
|
493
|
+
|
|
494
|
+
## Working Rules
|
|
495
|
+
|
|
496
|
+
- Prefer current code over stale memory.
|
|
497
|
+
- If docs and code disagree, trust code first and update docs.
|
|
498
|
+
- Do not invent ACP surface the runtime cannot actually honor.
|
|
499
|
+
- Keep examples runnable, explicit, and strongly typed.
|
|
500
|
+
- Treat adapter-owned state and host-owned state as different design choices.
|
|
501
|
+
- Prefer the narrowest seam that matches the user’s need.
|
|
502
|
+
- `FileSessionStore` uses `root=Path(...)`.
|
|
503
|
+
- `FileSessionStore` is the hardened local durable store, not a distributed session backend.
|
|
504
|
+
- Mode slash commands are dynamic, and mode ids must not collide with reserved names such as `model`, `thinking`, `tools`, `hooks`, or `mcp-servers`.
|
|
505
|
+
- `run_event_stream` hooks must return async iterables, not coroutines.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "ACP Kit SDK"
|
|
3
|
+
short_description: "Turn agent surfaces into ACP servers"
|
|
4
|
+
default_prompt: "Use $acpkit-sdk to update ACP Kit code, examples, or docs for turning an existing agent surface into a truthful ACP server."
|
|
5
|
+
|
|
6
|
+
policy:
|
|
7
|
+
allow_implicit_invocation: true
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# ACP Kit SDK Intro
|
|
2
|
+
|
|
3
|
+
ACP Kit is the adapter toolkit and monorepo for turning an existing agent surface into a truthful ACP server boundary.
|
|
4
|
+
|
|
5
|
+
Today the stable production focus is `pydantic-acp`: exposing `pydantic_ai.Agent` through ACP while keeping models, modes, plans, approvals, MCP metadata, host tools, and session state aligned with what the underlying runtime can actually support.
|
|
6
|
+
|
|
7
|
+
Additional adapters such as `langchain-acp` and `dspy-acp` are planned after `pydantic-acp` reaches 1.0 stability.
|
|
8
|
+
|
|
9
|
+
This intro is intentionally short. The canonical deep references should come from the published docs set, not from a second parallel skill-specific spec.
|
|
10
|
+
|
|
11
|
+
## Core Positioning
|
|
12
|
+
|
|
13
|
+
ACP Kit is not a new agent framework.
|
|
14
|
+
|
|
15
|
+
It sits between:
|
|
16
|
+
|
|
17
|
+
- an existing agent runtime
|
|
18
|
+
- ACP clients such as editors and host applications
|
|
19
|
+
|
|
20
|
+
The central contract is:
|
|
21
|
+
|
|
22
|
+
> expose ACP state only when the underlying runtime can actually honor it.
|
|
23
|
+
|
|
24
|
+
That rule drives model selection, mode switching, slash commands, native plan state, approval flow, MCP metadata, and host-backed tooling.
|
|
25
|
+
|
|
26
|
+
## Start With The Real Docs
|
|
27
|
+
|
|
28
|
+
Use these published docs pages as the primary references:
|
|
29
|
+
|
|
30
|
+
| Need | Published docs |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Product overview and package map | [ACP Kit Overview](https://vcoderun.github.io/acpkit/) |
|
|
33
|
+
| Construction seams and adapter overview | [Pydantic ACP Overview](https://vcoderun.github.io/acpkit/pydantic-acp/) |
|
|
34
|
+
| Runtime config and session ownership | [AdapterConfig](https://vcoderun.github.io/acpkit/pydantic-acp/adapter-config/) |
|
|
35
|
+
| Models, modes, slash commands, thinking | [Models, Modes, and Slash Commands](https://vcoderun.github.io/acpkit/pydantic-acp/runtime-controls/) |
|
|
36
|
+
| Plans, approvals, and cancellation | [Plans, Thinking, and Approvals](https://vcoderun.github.io/acpkit/pydantic-acp/plans-thinking-approvals/) |
|
|
37
|
+
| Host-owned state patterns | [Providers](https://vcoderun.github.io/acpkit/providers/) |
|
|
38
|
+
| ACP-visible extension seams | [Bridges](https://vcoderun.github.io/acpkit/bridges/) |
|
|
39
|
+
| Host-backed tools and projections | [Host Backends and Projections](https://vcoderun.github.io/acpkit/host-backends/) |
|
|
40
|
+
| Maintained example ladder | [Examples Overview](https://vcoderun.github.io/acpkit/examples/) |
|
|
41
|
+
| Production showcase | [Workspace Agent](https://vcoderun.github.io/acpkit/examples/workspace-agent/) |
|
|
42
|
+
| API surface | [pydantic_acp API](https://vcoderun.github.io/acpkit/api/pydantic_acp/) |
|
|
43
|
+
|
|
44
|
+
## Construction Seams To Reach For
|
|
45
|
+
|
|
46
|
+
Use these seams intentionally:
|
|
47
|
+
|
|
48
|
+
| Seam | Use it when |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `run_acp(agent=...)` | you want the smallest direct path from `pydantic_ai.Agent` to a running ACP server |
|
|
51
|
+
| `create_acp_agent(...)` | you need the ACP-compatible agent object before running it |
|
|
52
|
+
| `agent_factory=` | session context should influence agent construction, but a full custom source is unnecessary |
|
|
53
|
+
| `agent_source=` | you need full control over agent build path, host binding, and session-specific dependencies |
|
|
54
|
+
| built-in `AdapterConfig` fields | the adapter can own the relevant session state cleanly |
|
|
55
|
+
| providers | the host or product layer should remain the source of truth |
|
|
56
|
+
| bridges | the runtime needs ACP-visible capabilities without hard-coding them into the adapter core |
|
|
57
|
+
|
|
58
|
+
## High-Value Guardrails
|
|
59
|
+
|
|
60
|
+
- `FileSessionStore` takes `root=Path(...)`, not `base_dir=...`
|
|
61
|
+
- `FileSessionStore` is the hardened local durable store: atomic replace writes, local locking, malformed-session tolerance, and stale temp cleanup; it is not a distributed multi-writer backend
|
|
62
|
+
- slash mode commands are dynamic; `ask`, `plan`, and `agent` are examples, not built-in global names
|
|
63
|
+
- mode ids must not collide with reserved slash command names like `model`, `thinking`, `tools`, `hooks`, or `mcp-servers`
|
|
64
|
+
- only one `PrepareToolsMode(..., plan_mode=True)` is allowed
|
|
65
|
+
- `plan_tools=True` is how a non-plan execution mode keeps plan progress tools visible
|
|
66
|
+
- `/thinking` only exists when `ThinkingBridge()` is configured
|
|
67
|
+
- native ACP plan state and `PlanProvider` are separate ownership paths
|
|
68
|
+
- `HookBridge(hide_all=True)` suppresses hook listing output, not the underlying hook capability itself
|
|
69
|
+
- custom `run_event_stream` hooks and wrappers must return an async iterable, not a coroutine
|
|
70
|
+
|
|
71
|
+
## Reference Files In This Skill
|
|
72
|
+
|
|
73
|
+
These skill-local references are only routing aids back into the docs:
|
|
74
|
+
|
|
75
|
+
- `references/package-surface.md`
|
|
76
|
+
- `references/runtime-capabilities.md`
|
|
77
|
+
- `references/docs-examples-map.md`
|
|
78
|
+
|
|
79
|
+
Use them to find the right docs page quickly, not as independent source-of-truth specs.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
_EXAMPLE_DESCRIPTIONS = {
|
|
6
|
+
"approvals.py": "native deferred approval flow",
|
|
7
|
+
"bridges.py": "bridge builder and ACP-visible capabilities",
|
|
8
|
+
"factory_agent.py": "session-aware factory plus session-local model selection",
|
|
9
|
+
"hook_projection.py": "hook event labels and visibility controls",
|
|
10
|
+
"host_context.py": "client-backed filesystem and terminal helpers",
|
|
11
|
+
"providers.py": "host-owned models, modes, config, plan state, and approval metadata",
|
|
12
|
+
"static_agent.py": "smallest possible run_acp(agent=...) integration",
|
|
13
|
+
"strong_agent.py": "full workspace coding-agent showcase",
|
|
14
|
+
"strong_agent_v2.py": "alternative workspace integration shape",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _repo_root() -> Path:
|
|
19
|
+
return Path(__file__).resolve().parents[4]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main() -> None:
|
|
23
|
+
examples_dir = _repo_root() / "examples" / "pydantic"
|
|
24
|
+
for example_path in sorted(examples_dir.glob("*.py")):
|
|
25
|
+
if example_path.name == "__init__.py":
|
|
26
|
+
continue
|
|
27
|
+
description = _EXAMPLE_DESCRIPTIONS.get(example_path.name, "no mapped description")
|
|
28
|
+
print(f"{example_path.relative_to(_repo_root())}: {description}")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
main()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _repo_root() -> Path:
|
|
8
|
+
return Path(__file__).resolve().parents[4]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _extract_exports(module_path: Path) -> tuple[str, ...]:
|
|
12
|
+
module = ast.parse(module_path.read_text(encoding="utf-8"))
|
|
13
|
+
for node in module.body:
|
|
14
|
+
if isinstance(node, ast.Assign):
|
|
15
|
+
if len(node.targets) != 1:
|
|
16
|
+
continue
|
|
17
|
+
target = node.targets[0]
|
|
18
|
+
if isinstance(target, ast.Name) and target.id == "__all__":
|
|
19
|
+
value = ast.literal_eval(node.value)
|
|
20
|
+
if isinstance(value, tuple | list) and all(isinstance(item, str) for item in value):
|
|
21
|
+
return tuple(value)
|
|
22
|
+
raise ValueError(f"Could not locate __all__ in {module_path}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main() -> None:
|
|
26
|
+
root = _repo_root()
|
|
27
|
+
module_paths = {
|
|
28
|
+
"acpkit": root / "src" / "acpkit" / "__init__.py",
|
|
29
|
+
"pydantic_acp": root
|
|
30
|
+
/ "packages"
|
|
31
|
+
/ "adapters"
|
|
32
|
+
/ "pydantic-acp"
|
|
33
|
+
/ "src"
|
|
34
|
+
/ "pydantic_acp"
|
|
35
|
+
/ "__init__.py",
|
|
36
|
+
"codex_auth_helper": root
|
|
37
|
+
/ "packages"
|
|
38
|
+
/ "helpers"
|
|
39
|
+
/ "codex-auth-helper"
|
|
40
|
+
/ "src"
|
|
41
|
+
/ "codex_auth_helper"
|
|
42
|
+
/ "__init__.py",
|
|
43
|
+
}
|
|
44
|
+
for package_name, module_path in module_paths.items():
|
|
45
|
+
print(f"[{package_name}]")
|
|
46
|
+
for export_name in _extract_exports(module_path):
|
|
47
|
+
print(f"- {export_name}")
|
|
48
|
+
print()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
main()
|
|
@@ -25,9 +25,9 @@ jobs:
|
|
|
25
25
|
- name: Install dependencies
|
|
26
26
|
run: |
|
|
27
27
|
uv venv
|
|
28
|
-
uv pip install -e ".[docs]"
|
|
28
|
+
uv pip install -e ".[docs,pydantic,codex]"
|
|
29
29
|
|
|
30
30
|
- name: Deploy MkDocs
|
|
31
31
|
run: |
|
|
32
32
|
source .venv/bin/activate
|
|
33
|
-
mkdocs gh-deploy --force
|
|
33
|
+
mkdocs gh-deploy --force --strict
|