Skip to main content

Python ACP client library — connect to 29 AI coding agents with zero session overhead

Project description

soulacp

CI Python License

Python ACP client library — connect to AI coding agents with zero session overhead.

Features

  • 29 CLI adapters: Claude Code, Gemini, OpenCode, OpenClaw, Cursor, Codex, Qwen, Kimi, Codebuddy, Cline, Copilot, Minion, Vibe, Nova, Crow, Amp, Auggie, Autohand, Corust, DeepAgents, Factory Droid, fast-agent, Copilot LS, Goose, Junie, Kilo, pi ACP, Qoder, Stakpak
  • No own session layer: Directly manages CLI's native session
  • Zero token overhead: No middleware, no duplicate session history
  • ManagedSession: High-level API with auto session reuse, rotation, retry, fallback
  • Connection pooling: Reuse idle connections, session matching
  • Session store: Persistent user→session mapping with TTL (Memory or File cache)
  • Async streaming: Real-time response chunks via asyncio
  • Auto-retry: Exponential backoff with jitter
  • Host services: Built-in file system and terminal services for CLI tool calls
  • Pure stdlib: No external dependencies

Install

pip install soulacp

Quick Start

ManagedSession (recommended)

import asyncio
from soulacp import ManagedSession

async def main():
    async with ManagedSession(provider="claude", model="claude-sonnet-4-20250514") as session:
        # Simple query — session auto-managed
        response = await session.query("Hello!", user_id="user1")
        print(response)

        # Streaming
        async for chunk in session.stream("Write hello world", user_id="user1"):
            print(chunk, end="", flush=True)

asyncio.run(main())

ManagedSession automatically handles:

  • Session reuse: Same user_id gets same CLI session across requests
  • Session rotation: Fresh session on "prompt too long" overflow
  • Retry: Exponential backoff on transient errors
  • Fallback: Switch to alternate provider on persistent failure

Low-level API

import asyncio
from soulacp import ACPConfig, ACPConnectionPool, resolve_client_class

async def main():
    config = ACPConfig(provider="claude", model="claude-sonnet-4-20250514")
    client_class = resolve_client_class("claude")
    pool = ACPConnectionPool(config, client_class)

    async with pool.acquire() as (client, session_id):
        response = await client.query("Hello!")
        print(response)

    await pool.close_all()

asyncio.run(main())

Supported Agents

Agent Provider Model Example CLI Command
Claude Code claude claude-sonnet-4-20250514 claude or claude-code-acp
Gemini gemini gemini-3-flash-preview gemini --acp
OpenCode opencode opencode acp
OpenClaw openclaw openclaw acp
Cursor (ACP) cursor cursor-acp/default cursor-agent acp
Cursor (Legacy) cursor-cli cursor-cli/gpt-4 cursor-agent -p
Codex codex codex-acp/gpt-5 codex-acp
Qwen Code qwen qwen-acp/qwen-coder qwen-code --acp --experimental-skills
Kimi CLI kimi kimi-acp/default kimi acp
Codebuddy Code codebuddy codebuddy-acp/default codebuddy-code --acp
Cline cline cline-acp/default cline --acp
GitHub Copilot copilot copilot-acp/default copilot --acp
Minion Code minion minion-acp/default minion-code acp
Mistral Vibe vibe vibe-acp/default vibe-acp
Nova nova nova-acp/default nova acp
Crow CLI crow crow-acp/default crow-cli acp
Amp amp amp-acp/default amp-acp
Auggie auggie auggie-acp/default auggie --acp
Autohand autohand autohand-acp/default autohand-acp
Corust Agent corust corust-acp/default corust-agent-acp
DeepAgents deepagents deepagents-acp/default deepagents-acp
Factory Droid droid droid-acp/default droid exec --output-format acp
fast-agent fastagent fastagent-acp/default fast-agent-acp -x
Copilot LS copilot-ls copilot-ls-acp/default copilot-language-server --acp
Goose goose goose-acp/default goose acp
Junie junie junie-acp/default junie --acp=true
Kilo kilo kilo-acp/default kilo acp
pi ACP pi pi-acp/default pi-acp
Qoder qoder qoder-acp/default qodercli --acp
Stakpak stakpak stakpak-acp/default stakpak acp

Usage

Claude Code

import asyncio
from soulacp import ManagedSession

async def main():
    async with ManagedSession(provider="claude", model="claude-sonnet-4-20250514") as session:
        response = await session.query("Hello!")
        print(response)

asyncio.run(main())

Gemini

import asyncio
from soulacp import ManagedSession

async def main():
    async with ManagedSession(provider="gemini", model="gemini-3-flash-preview") as session:
        response = await session.query("Hello!")
        print(response)

asyncio.run(main())

Multi-Agent

import asyncio
from soulacp import ManagedSession

async def main():
    # Claude for code generation
    async with ManagedSession(provider="claude", model="claude-sonnet-4-20250514") as claude:
        code = await claude.query("Write a sorting algorithm in Python")

    # Gemini for code review
    async with ManagedSession(provider="gemini", model="gemini-3-flash-preview") as gemini:
        review = await gemini.query(f"Review this code:\n{code}")

asyncio.run(main())

Session Management

ManagedSession + ProviderSessionStore

ManagedSession uses ProviderSessionStore internally to map (user_id, provider) to CLI session IDs:

from soulacp import ManagedSession

session = ManagedSession(provider="claude", model="claude-sonnet-4-20250514")

# First request — creates new CLI session, stores mapping
await session.query("Remember 42.", user_id="alice")

# Second request — reuses same CLI session (alice→session_abc)
await session.query("What number?", user_id="alice")

# Different user — gets different CLI session
await session.query("Hello!", user_id="bob")

Custom Session Store

from soulacp import ManagedSession, ProviderSessionStore, FileCache

# Persistent file-based session store
store = ProviderSessionStore(cache=FileCache("~/.soulacp/sessions.json"))
session = ManagedSession(provider="claude", model="claude-sonnet-4-20250514", session_store=store)

Session Lifecycle

Event Behavior
First request New CLI session created, mapping stored (TTL 7 days)
Subsequent requests Same user_id → same CLI session (reuse)
"Prompt too long" Auto-rotate to fresh session, clear old mapping
Connection error Clear mapping, retry with new session
Fallback Switch to alternate provider (e.g. claude→gemini)

Cache Backends

from soulacp import MemoryCache, FileCache

# In-memory (default) — fast, lost on restart
memory = MemoryCache(max_size=10000)

# File-based — persists across restarts
file_cache = FileCache("~/.soulacp/sessions.json", debounce_seconds=1.0)

Low-level Session Control

from soulacp import ACPConnectionPool, ACPConfig, resolve_client_class

config = ACPConfig(provider="claude", model="claude-sonnet-4-20250514")
pool = ACPConnectionPool(config, resolve_client_class("claude"))

# Explicit session reuse
async with pool.acquire() as (client, sid):
    await client.query("Remember 42.")

async with pool.acquire(session_id=sid) as (client, sid2):
    assert sid2 == sid  # Same CLI session
    response = await client.query("What number?")

Configuration

Environment Variables

Variable Default Description
ACP_PROVIDER Provider name
ACP_MODEL Model identifier
ACP_POOL_SIZE 10 Max pool connections
ACP_TIMEOUT_CONNECT 30 Connection timeout (seconds)
ACP_TIMEOUT_PROMPT 3600 Prompt timeout (seconds)
ACP_AUTO_APPROVE true Auto-approve tool permissions
ACP_MAX_RETRIES 3 Max retry attempts

Programmatic

from soulacp import ACPConfig

config = ACPConfig(
    provider="claude",
    model="claude-sonnet-4-20250514",
    pool_size=5,
    timeout_connect=60,
    auto_approve_permissions=True,
    enable_fallback=True,
)

From Environment

from soulacp import ACPConfig

config = ACPConfig.from_env()

Architecture

ManagedSession (high-level API)
  ├── ProviderSessionStore (user→session mapping)
  │   └── CacheBackend (MemoryCache / FileCache)
  ├── ACPConnectionPool (connection reuse + health check)
  │   └── ACPClientBase (JSON-RPC over stdio subprocess)
  │       ├── ClaudeACPClient      ├── ClineACPClient
  │       ├── GeminiACPClient      ├── CopilotACPClient
  │       ├── OpenCodeACPClient    ├── MinionACPClient
  │       ├── OpenClawACPClient    ├── VibeACPClient
  │       ├── CursorACPClient      ├── NovaACPClient
  │       ├── CodexACPClient       ├── CrowACPClient
  │       ├── QwenACPClient        └── CursorCLIClient (legacy)
  │       ├── KimiACPClient
  │       └── CodebuddyACPClient
  └── Services
      ├── FSService (file system operations)
      └── TerminalService (subprocess execution)

Testing

# Unit tests (no CLI required)
pytest tests/ --ignore=tests/test_integration*.py -v

# Integration tests (requires specific CLI installed, auto-skips if not available)
pytest tests/test_integration.py -v          # Claude Code
pytest tests/test_integration_gemini.py -v   # Gemini
pytest tests/test_integration_codex.py -v    # Codex

# All tests
pytest tests/ -v

AIXP Labs aixp.dev

AIXP Labs develops and maintains the following core projects:

Project Description Website
HSAW Human Sovereignty and Wellbeing — Axiom 0 white paper (foundation) hsaw.dev
AILP AI List Protocol — agent discovery and capability advertising ailp.dev
AIVP AI Value Protocol — international commerce, crypto asset settlement aivp.dev
AIRP AI RMB Protocol — Mainland China commerce, RMB licensed settlement airp.dev
AIBP AI Bot Protocol — social communication and trust aibp.dev
AIAP AI Application Protocol — governance and compliance aiap.dev
AISOP AI Standard Operating Protocol — flow program definition aisop.dev
SoulBot AI agent runtime and framework soulbot.dev
SoulACP Adapter library — bridging CLI tools and LLM providers (this project) soulacp.dev

License

Apache License 2.0 - Copyright 2026 AIXP Labs AIXP.dev | SoulACP.dev


Align Axiom 0: Human Sovereignty and Wellbeing. Version: SoulACP V0.1.2. www.soulacp.dev

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

soulacp-0.1.3.tar.gz (66.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

soulacp-0.1.3-py3-none-any.whl (84.7 kB view details)

Uploaded Python 3

File details

Details for the file soulacp-0.1.3.tar.gz.

File metadata

  • Download URL: soulacp-0.1.3.tar.gz
  • Upload date:
  • Size: 66.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for soulacp-0.1.3.tar.gz
Algorithm Hash digest
SHA256 2d18f7a549f05a1500e75fa79b71005b30b267302738537a4321e2a4e255add5
MD5 341705fbced4a82bc6a894dd9c2f9304
BLAKE2b-256 e329853f8c3010367ee6f2856c1e5fd923dc24e036cff390c658bd6908075e60

See more details on using hashes here.

File details

Details for the file soulacp-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: soulacp-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 84.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for soulacp-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2a8ba38e62c4e5a9198667e26aff727212a797794fd9c951dc068470846b734c
MD5 cd08b59b48032f1f269f3c0daf4b29e3
BLAKE2b-256 a8b10d43181c93307c91a63e1374da55ad866396b9a58a32c417e0734ac0bb70

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page