Metadata-Version: 2.4
Name: covo-sdk
Version: 0.3.7
Summary: Connect your own Python agent to a shared Covo session: live team viewing, one controller, approvals, pause and interrupt.
Author: Ulaş Taylan Met
Keywords: agent,ai,collaboration,llm,observability,openai,team,websocket
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: python-socketio[asyncio_client]<6,>=5.11
Requires-Dist: aiohttp<4,>=3.9
Requires-Dist: certifi>=2024.2.2
Provides-Extra: openai
Requires-Dist: openai<4,>=1.50; extra == "openai"

# Covo Python SDK

Connect the Python agent you already have to a shared **Covo** session. Your teammates open one link, watch the same run live (model calls, tool calls, results, files, errors), and exactly one person at a time holds control: new instructions, pause/resume, interrupt, approve/reject, hand over control.

The agent keeps running on **your** machine or server. Your LLM keys, files and tools never leave it; only the events you share reach Covo.

Türkçe tam rehber: Covo panelinde `/integrate`.

## Install

```bash
pip install "covo-sdk[openai]"
```

Python 3.11+, asyncio. The `openai` extra is only needed if you use `instrument()` with the OpenAI Python client; any OpenAI-compatible endpoint works (OpenAI, OpenRouter, DeepSeek, Ollama, vLLM, ...).

## Three lines of integration

```python
from openai import AsyncOpenAI
from covo_sdk import CovoOwner, instrument, tool

llm = instrument(AsyncOpenAI())            # 1. every model call is shared automatically

@tool(approve=True)                         # 2. tool calls are shared; this one needs approval
async def write_file(path: str, content: str) -> str:
    open(path, "w").write(content)
    return "saved"

async def run(ctx) -> str:                  # 3. your existing agent loop, unchanged
    completion = await llm.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[{"role": "user", "content": ctx.instruction}],
    )
    return completion.choices[0].message.content
```

Start it from your terminal; Covo creates the shared session and prints the link:

```python
import asyncio

async def main():
    owner = await CovoOwner.login(url="https://covo.example.com", name="Ulaş")
    client = await owner.connect(
        run=run, name="Research agent",
        capabilities=["instruct", "pause", "resume", "interrupt", "approval"],
    )
    print("Share with your team:", client.share_url)
    print("Private owner code (do not share):", await owner.browser_code())
    await client.start("Read README.md and propose a plan.")
    await client.wait()

asyncio.run(main())
```

## What the SDK does for you

| You write | Covo shows | Guarantees |
| --- | --- | --- |
| `instrument(client)` | `model_call` / `model_result` with the real prompt, response, measured latency and provider-reported tokens | Streaming supported; calls outside a run pass through untouched; nothing is estimated or invented |
| `@tool` | `tool_call` / `tool_completed` with the bound arguments, result or error, duration | Sync tools run inline and bounded; async tools are cancellable for interrupt |
| `@tool(approve=True)` | An approval card with the exact arguments; only the controller can decide | The function body never runs on rejection (`ToolRejected`, or your `rejected=` value) |
| `await ctx.checkpoint()` | Pause is acknowledged here | Covo never claims "paused" before the agent actually stopped at a checkpoint |
| `await ctx.emit(...)` | Anything else you want visible (`thinking`, `resource`) | Redaction callback can filter content, never control data |

Manual control for raw HTTP callers:

```python
from covo_sdk import model_span

async with model_span(model, messages) as span:
    payload = await http.post(url, json=request)
    span.result(payload["choices"][0]["message"], tokens=payload["usage"]["total_tokens"])
```

## Share a Claude Code session without writing code

```bash
covo --url https://covo.example.com --name "Ulaş" claude-code install
cd ~/work/product && covo claude-code enable   # only sessions started here are shared
```

Registers Claude Code hooks. Installing shares nothing on its own: a session reaches Covo only from a directory you enabled, when you run `/covo-share` inside Claude Code, or when it was started with `COVO=1` (`COVO=0` turns it off for one terminal). Every other session behaves as if Covo were not installed — no daemon, no waiting, no gated tools. A shared session prints a Covo share link; teammates watch tool calls, results and the final answer live, and the controller approves or rejects gated tools (default: Write, Edit, MultiEdit, NotebookEdit, Bash) from Covo. Watch-and-approve only: Covo cannot instruct, pause or interrupt Claude Code, and once control is handed to a teammate the owner's own terminal is blocked from new prompts until it returns. macOS, Linux and Windows 10+ (Git Bash, as Claude Code requires).

## Control model

- One controller per session, enforced server-side. Terminal and browser commands go through the same check; handing over control also locks out the owner's own terminal.
- Interrupt cancels the running asyncio task and waits for cleanup before the replacement run starts. Do not swallow `CancelledError`; avoid detached threads.
- Declare only the capabilities your agent honors. Unsupported controls are disabled in the UI.
- Credentials live in `.covo/` with owner-only permissions. Add `.covo/` to `.gitignore`. Share only the session link.
- HTTPS is required beyond localhost. For a Covo on a trusted LAN (private IP or `.local` host) pass `allow_insecure_http=True` (CLI: `--allow-insecure-http`); it is your explicit risk decision, the traffic is unencrypted and a non-private address triggers a stronger warning; use HTTPS over the internet.

## CLI

```bash
covo --version
covo claude-code enable       # share Claude Code sessions started in this directory
covo claude-code disable      # stop sharing them
covo claude-code status       # scope, enabled directories, running sessions
covo code                     # new private owner code for the browser
covo state <session-id>
covo command <session-id> pause
covo command <session-id> interrupt --text "Stop, use PostgreSQL instead."
```

## Limits

Alpha. Python 3.11+ async agents only. The SDK must be wired into the agent before the run starts; it cannot attach to an already-running process. No automatic resume after a crash: Covo marks the old run failed and waits for a new instruction. Anyone with a session link can watch, so deploy Covo for a trusted team.
