Metadata-Version: 2.4
Name: langchain-acp
Version: 0.9.3
Summary: Expose LangChain and LangGraph agents through ACP Kit.
Project-URL: Homepage, https://vcoderun.github.io/acpkit/langchain-acp/
Project-URL: Issues, https://github.com/vcoderun/acpkit/issues
Project-URL: Repository, https://github.com/vcoderun/acpkit
License: Apache 2.0
Keywords: acp,agents,langchain,langgraph,protocol
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: agent-client-protocol>=0.9.0
Requires-Dist: langchain>=1.0.0
Requires-Dist: langgraph>=1.0.0
Requires-Dist: pydantic>=2.7
Requires-Dist: typing-extensions>=4.12.0
Provides-Extra: deepagents
Requires-Dist: deepagents>=0.5.0; extra == 'deepagents'
Description-Content-Type: text/markdown

# langchain-acp

`langchain-acp` exposes LangChain, LangGraph, and DeepAgents graphs through ACP Kit.

It keeps ACP Kit's adapter architecture intact while staying graph-centric on the LangChain side:

- `graph=...`
- `graph_factory=...`
- `graph_source=...`

## Install

```bash
uv add langchain-acp
```

```bash
pip install langchain-acp
```

With optional DeepAgents compatibility:

```bash
uv add "langchain-acp[deepagents]"
```

```bash
pip install "langchain-acp[deepagents]"
```

Contributor setup from the monorepo root:

```bash
uv sync --extra dev --extra langchain
```

## Quickstart

```python
from langchain.agents import create_agent
from langchain_acp import run_acp

graph = create_agent(model="openai:gpt-5", tools=[])

run_acp(graph=graph)
```

If you are using Codex-backed LangChain models through `codex-auth-helper`, you must pass the
LangChain system behavior through the helper's `instructions=` argument. The same repo policy now
applies on the Pydantic path too: Codex-backed model factories take explicit instructions instead of
inventing an implicit default.

```python
from codex_auth_helper import create_codex_chat_openai
from langchain.agents import create_agent

model = create_codex_chat_openai(
    "gpt-5.4",
    instructions="You are a careful assistant that explains concrete workspace observations.",
)
graph = create_agent(model=model, tools=[], name="codex-graph")
```

That `instructions` string is required and is forwarded to the OpenAI Responses request behind
`ChatOpenAI`. See the maintained example at
<https://github.com/vcoderun/acpkit/blob/main/examples/langchain/codex_graph.py>.

Use the same pattern inside `graph_factory=` paths too. If the graph is rebuilt per session, keep
the Codex system behavior explicit in the factory instead of relying on an implicit default:

```python
from codex_auth_helper import create_codex_chat_openai
from langchain.agents import create_agent
from langchain_acp import AcpSessionContext


def graph_from_session(session: AcpSessionContext):
    mode_name = session.session_mode_id or "ask"
    model_name = session.session_model_id or "gpt-5.4-mini"
    model = create_codex_chat_openai(
        model_name,
        instructions=f"Operate in {mode_name} mode and explain concrete workspace observations.",
    )
    return create_agent(model=model, tools=[], name=f"codex-{mode_name}")
```

If ACP session state should affect graph construction, use `graph_factory=`:

```python
from langchain.agents import create_agent
from langchain_acp import AcpSessionContext, create_acp_agent


def graph_from_session(session: AcpSessionContext):
    mode_name = session.session_mode_id or "default"
    return create_agent(model="openai:gpt-5", tools=[], name=f"graph-{mode_name}")


acp_agent = create_acp_agent(graph_factory=graph_from_session)
```

## What The Adapter Covers

`langchain-acp` carries the same ACP Kit seams that matter elsewhere in the repo, but mapped onto graph ownership instead of agent ownership:

- session stores and transcript replay
- model, mode, and config-option providers
- prompt capability advertisement through `prompt_capabilities`
- native plan state through `TaskPlan`
- approval bridging from `HumanInTheLoopMiddleware`
- remembered approval policies and permission card rendering on `NativeApprovalBridge`
- capability bridges and graph-build contributions
- built-in and host-defined slash commands
- tool projection maps and event projection maps
- external hook/event projection through `ExternalHookEventBridge`
- `graph`, `graph_factory`, and `graph_source`
- DeepAgents compatibility helpers where they add truthful ACP behavior

That means the adapter can expose:

- plain LangChain `create_agent(...)` graphs
- compiled LangGraph graphs
- DeepAgents graphs

without collapsing everything into a bespoke ACP runtime.

## Runtime Controls

The adapter now owns a small ACP-native slash-command layer instead of leaving that surface entirely to the graph:

- mode commands such as `/ask` or `/review` when the session publishes modes
- `/model` for ACP-owned model selection
- `/tools` for the active graph tool node
- `/mcp-servers` for attached session MCP servers
- custom host commands through `slash_command_provider`

Example:

```python
from acp.schema import AvailableCommand
from langchain_acp import (
    AdapterConfig,
    SlashCommandResult,
    StaticSlashCommand,
    StaticSlashCommandProvider,
)

config = AdapterConfig(
    slash_command_provider=StaticSlashCommandProvider(
        commands=[
            StaticSlashCommand(
                command=AvailableCommand(name="ping", description="Return pong."),
                handler=lambda _request: SlashCommandResult(text="pong"),
            )
        ]
    )
)
```

Prompt capability advertisement is also explicit now:

```python
from langchain_acp import AdapterConfig, AdapterPromptCapabilities

config = AdapterConfig(
    prompt_capabilities=AdapterPromptCapabilities(
        audio=False,
        image=False,
        embedded_context=True,
    )
)
```

If the graph uses approval middleware, remembered choices and ACP permission presentation stay on
`NativeApprovalBridge`, not on `AdapterConfig`:

```python
from langchain_acp import NativeApprovalBridge

config = AdapterConfig(
    approval_bridge=NativeApprovalBridge(enable_persistent_choices=True),
)
```

## Session-owned Graph Rebuilds

If ACP session state should decide which graph gets built, `graph_factory=` is the intended seam:

```python
from langchain.agents import create_agent
from langchain_acp import AcpSessionContext, AdapterConfig, MemorySessionStore, run_acp


def graph_from_session(session: AcpSessionContext):
    mode_name = session.session_mode_id or "default"
    model_name = session.session_model_id or "openai:gpt-5-mini"
    return create_agent(
        model=model_name,
        tools=[],
        name=f"graph-{mode_name}",
        system_prompt=f"Operate in {mode_name} mode.",
    )


run_acp(
    graph_factory=graph_from_session,
    config=AdapterConfig(session_store=MemorySessionStore()),
)
```

Use this when workspace path, mode, model, or session metadata should rebuild the graph dynamically.

The maintained examples under `examples/langchain/` also expose ACP-visible model and mode choices
through `available_models`, `available_modes`, `default_model_id`, and `default_mode_id`, then
consume `session.session_model_id` and `session.session_mode_id` inside `graph_factory=...`.

## DeepAgents Compatibility

DeepAgents graphs are supported as compiled LangGraph targets.

Use the compatibility helpers only when they add real value:

- `DeepAgentsCompatibilityBridge`
- `DeepAgentsProjectionMap`

Maintained examples:

- [workspace_graph.py](https://github.com/vcoderun/acpkit/blob/main/examples/langchain/workspace_graph.py)
- [deepagents_graph.py](https://github.com/vcoderun/acpkit/blob/main/examples/langchain/deepagents_graph.py)

Docs:

- <https://vcoderun.github.io/acpkit/langchain-acp/>
- <https://vcoderun.github.io/acpkit/getting-started/langchain-quickstart/>
- <https://vcoderun.github.io/acpkit/examples/langchain-workspace/>
- <https://vcoderun.github.io/acpkit/examples/deepagents/>
