Metadata-Version: 2.4
Name: evolv-agent-sdk
Version: 0.2.0
Summary: Python SDK for evolv Code
Project-URL: Homepage, https://github.com/jeremy-newhouse/evolv-code
Project-URL: Documentation, https://github.com/jeremy-newhouse/evolv-code/tree/main/packages/sdk
Project-URL: Issues, https://github.com/jeremy-newhouse/evolv-code/issues
Author-email: evolv <support@evolv.ai>
License: MIT
License-File: LICENSE
Keywords: agent,ai,claude,evolv,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: anyio>=4.0.0
Requires-Dist: mcp>=0.1.0
Requires-Dist: typing-extensions>=4.0.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: anyio[trio]>=4.0.0; extra == 'dev'
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.20.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# evolv Agent SDK for Python

Python SDK for [evolv Code](https://github.com/evolv-ai/evolv-code), an AI coding assistant with full bidirectional streaming support.

## Installation

```bash
pip install evolv-agent-sdk
```

**Note:** The evolv Code CLI must be installed separately. Build from source at `/Users/jdnewhouse/repos/evolv-code` or set `EVOLV_CODE_CLI_PATH` environment variable.

## Quick Start

### Simple Query

```python
import asyncio
from evolv_agent_sdk import query, EvolvAgentOptions, AssistantMessage, TextBlock

async def main():
    async for message in query(prompt="What is 2 + 2?"):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(f"evolv: {block.text}")

asyncio.run(main())
```

### Multi-Query Client

```python
import asyncio
from evolv_agent_sdk import EvolvSDKClient, EvolvAgentOptions, AssistantMessage, TextBlock

async def main():
    async with EvolvSDKClient() as client:
        # First query
        await client.query("What files are in this directory?")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(block.text)

        # Second query (note: each query is independent)
        await client.query("How many are Python files?")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(block.text)

asyncio.run(main())
```

### Bidirectional Streaming Mode

evolv Code CLI supports full bidirectional streaming with `--input-format stream-json`:

```python
import asyncio
from evolv_agent_sdk import query, EvolvAgentOptions
from evolv_agent_sdk.types import PermissionResultAllow, PermissionResultDeny

async def my_can_use_tool(tool_name, tool_input, context):
    """Custom tool permission callback."""
    if tool_name == "Bash" and "rm" in tool_input.get("command", ""):
        return PermissionResultDeny(message="Destructive command blocked")
    return PermissionResultAllow()

async def main():
    options = EvolvAgentOptions(
        can_use_tool=my_can_use_tool,
    )

    async for message in query(
        prompt=my_async_input_generator(),  # AsyncIterable for streaming
        options=options,
    ):
        print(message)

asyncio.run(main())
```

## API Reference

### `query()`

One-shot query function for simple, stateless interactions.

```python
async for message in query(
    prompt="Your question here",
    options=EvolvAgentOptions(
        cwd="/path/to/working/directory",
        model="your-model",
    )
):
    print(message)
```

### `EvolvSDKClient`

Client for running multiple queries. Each query spawns a new process.

```python
async with EvolvSDKClient(options) as client:
    await client.query("First question")
    async for msg in client.receive_response():
        print(msg)

    await client.query("Second question")
    async for msg in client.receive_response():
        print(msg)
```

### `EvolvAgentOptions`

Configuration options for the SDK:

| Option | Type | Description |
|--------|------|-------------|
| `cli_path` | `str \| Path` | Path to evolv CLI binary |
| `cwd` | `str \| Path` | Working directory for commands |
| `model` | `str` | Model to use |
| `connection` | `str` | Snowflake connection name |
| `resume` | `str` | Session ID to resume |
| `continue_conversation` | `bool` | Continue most recent session |
| `env` | `dict[str, str]` | Environment variables |
| `can_use_tool` | `Callable` | Tool permission callback (bidirectional mode) |
| `hooks` | `dict` | SDK hooks for PreToolUse, PostToolUse, etc. |
| `mcp_servers` | `dict` | SDK MCP servers (in-process) |

## Environment Variables

| Variable | Description |
|----------|-------------|
| `EVOLV_CODE_CLI_PATH` | Path to evolv CLI binary |
| `EVOLV_CODE_ENTRYPOINT` | SDK entrypoint identifier |
| `EVOLV_AGENT_SDK_SKIP_VERSION_CHECK` | Skip CLI version check |
| `EVOLV_CODE_STREAM_CLOSE_TIMEOUT` | Timeout for stream close (ms) |

## Message Types

The SDK yields several message types:

- `AssistantMessage` - Response from evolv with content blocks
- `UserMessage` - User input messages
- `SystemMessage` - System notifications
- `ResultMessage` - Final result with metadata

### Content Blocks

`AssistantMessage.content` contains a list of content blocks:

- `TextBlock` - Text response
- `ThinkingBlock` - Internal reasoning (if enabled)
- `ToolUseBlock` - Tool invocation
- `ToolResultBlock` - Tool execution result

## Features

### Bidirectional Streaming

evolv Code CLI supports `--input-format stream-json` for full bidirectional communication:

| Feature | evolv Code | Cortex Code |
|---------|------------|-------------|
| `--input-format stream-json` | ✅ Supported | ❌ Not available |
| `can_use_tool` callback | ✅ Supported | ❌ Not available |
| `interrupt()` | ✅ Supported | ❌ Not available |
| `set_permission_mode()` | ✅ Supported | ❌ Not available |
| `set_model()` | ✅ Supported | ❌ Not available |
| SDK Hooks | ✅ Supported | ❌ Not available |
| SDK MCP Servers | ✅ Supported | ❌ Not available |

### Fallback Mode

When using Cortex CLI (without bidirectional support), the SDK falls back to print mode:

```python
# Use --continue to resume the most recent session
options = EvolvAgentOptions(continue_conversation=True)

# Or resume a specific session
options = EvolvAgentOptions(resume="session-id-here")
```

## Backward Compatibility

For migration from Claude Agent SDK or Cortex Agent SDK:

```python
from evolv_agent_sdk import (
    # Claude aliases
    ClaudeSDKClient,      # Alias for EvolvSDKClient
    ClaudeAgentOptions,   # Alias for EvolvAgentOptions
    ClaudeSDKError,       # Alias for EvolvSDKError

    # Cortex aliases
    CortexSDKClient,      # Alias for EvolvSDKClient
    CortexAgentOptions,   # Alias for EvolvAgentOptions
    CortexSDKError,       # Alias for EvolvSDKError
)
```

## License

MIT License - see [LICENSE](LICENSE) for details.

## Links

- [evolv Code CLI](https://github.com/evolv-ai/evolv-code)
- [GitHub Repository](https://github.com/evolv-ai/evolv-agent-sdk-python)
- [Issue Tracker](https://github.com/evolv-ai/evolv-agent-sdk-python/issues)
