Metadata-Version: 2.3
Name: karta-runtime
Version: 0.6.72
Summary: Karta agent runtime: harness adapters, dev serve, and the platform serve layer
License: MIT License
         
         Copyright (c) 2026 LifeSage LLC
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
Keywords: agents,ai,framework,orchestration
Author: Karta
Author-email: team@karta.sh
Requires-Python: >=3.11,<3.14
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.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Framework :: FastAPI
Provides-Extra: dev-reload
Provides-Extra: gitmerge
Provides-Extra: otel
Provides-Extra: postgres
Provides-Extra: s3
Requires-Dist: anyio (>=4.14.2,<5.0.0)
Requires-Dist: backoff (>=2.2.1,<3.0.0)
Requires-Dist: boto3 (>=1.35.92,<2.0.0) ; extra == "s3"
Requires-Dist: claude-agent-sdk (>=0.2.82,<0.3.0) ; python_version >= "3.10"
Requires-Dist: cryptography (>=44,<50)
Requires-Dist: dulwich (>=1.2.11,<2.0.0)
Requires-Dist: fastapi (>=0.139.2,<0.140.0)
Requires-Dist: httpcore (>=1.0.9,<2.0.0)
Requires-Dist: httpx (>=0.28.1,<0.29.0)
Requires-Dist: jsonschema (>=4.23.0,<5.0.0)
Requires-Dist: litellm (==1.92.0)
Requires-Dist: markdown-it-py (>=3.0,<5.0)
Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0) ; extra == "otel"
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-asgi (>=0.48b0,<1.0) ; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.48b0,<1.0) ; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.48b0,<1.0) ; extra == "otel"
Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0) ; extra == "otel"
Requires-Dist: orjson (>=3.11.6,<4.0.0)
Requires-Dist: psycopg-pool (>=3.3.1,<4.0.0) ; extra == "postgres"
Requires-Dist: psycopg[binary] (>=3.2.3,<4.0.0) ; extra == "postgres"
Requires-Dist: pydantic (>=2.10.4,<3.0.0)
Requires-Dist: pygit2 (>=1.18.0,<2.0.0) ; (python_version >= "3.11") and (extra == "gitmerge")
Requires-Dist: python-frontmatter (>=1.1.0,<2.0.0)
Requires-Dist: rich (>=13.0.0,<16.0.0)
Requires-Dist: typer (>=0.21,<0.27)
Requires-Dist: uvicorn[standard] (>=0.50.0,<0.52.0)
Requires-Dist: watchfiles (>=1.0.0,<2.0.0) ; extra == "dev-reload"
Project-URL: Documentation, https://docs.karta.sh
Project-URL: Homepage, https://karta.sh
Project-URL: Repository, https://github.com/karta-sh/karta
Description-Content-Type: text/markdown

<div align="center">
  <h1>karta-runtime</h1>
  <p><strong>The Karta runtime: harness adapters, sessions, and the consumer session API on agent harnesses like Claude Code and OpenCode</strong></p>
</div>

<div align="center">

[![GitHub License](https://img.shields.io/github/license/karta/karta?logo=github)](https://github.com/karta/karta/blob/main/LICENSE)
[![PyPI Version](https://img.shields.io/pypi/v/karta-runtime?logo=pypi&color=blue)](https://pypi.org/project/karta-runtime/)
[![Python Version](https://img.shields.io/badge/Python-3.9--3.12-blue?logo=python)](https://www.python.org/)
[![GitHub issues](https://img.shields.io/github/issues/karta/karta)](https://github.com/karta/karta/issues)

</div>

> **Looking for the `karta` command?** The public CLI is
> [`@karta.sh/cli`](../../sdks/typescript-cli/) (`npm install -g @karta.sh/cli`).
> This package is `karta-runtime` - the internal engine that CLI bootstraps
> for `karta dev`, and the data plane the platform serves (RFC 0013,
> [docs/rfcs/0013-unified-cli.md](../../docs/rfcs/0013-unified-cli.md)). Its
> own CLI verbs are internal (see [CLI](#cli-internal)); use it directly as a
> Python SDK/library, exactly as documented below.

## Why Karta

Agent frameworks like [LangGraph](https://github.com/langchain-ai/langgraph), [CrewAI](https://github.com/crewAIInc/crewAI), [AutoGen](https://github.com/microsoft/autogen), and the [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) build agents from scratch — defining their own tool systems, context management, memory, and execution loops.

**Karta takes the opposite approach.** Agent harnesses like [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and [OpenCode](https://opencode.ai) already solved the hard problems — tools, MCP servers, context management, memory, skills, and agentic execution. They're battle-tested, deeply integrated with real development workflows, and improving fast.

Karta builds **on top** of these harnesses in two tiers: a **thin core** that delegates all agent execution and conversation persistence to the harness, plus a **platform layer** that adds the multi-tenant SaaS machinery production applications need. Together they provide **multi-user sessions**, **multi-agent routing**, **participant-aware messaging**, **cross-instance communication**, **HTTP deployment**, **multi-tenancy with durable tenant isolation**, **BYOK key management**, **usage metering**, **policy enforcement**, and **lifecycle hooks** — without reinventing agent capabilities from scratch.

```
┌──────────────────────────────────────────────────────────┐
│  Other frameworks          │  Karta                      │
│                            │                              │
│  Build agents from scratch │  Build ON existing harnesses │
│  Own tool system           │  Harness tools (MCP, etc.)   │
│  Own memory/context        │  Harness memory/context      │
│  Own execution loop        │  Harness execution loop      │
│  + Multi-agent orchestr.   │  + Multi-user sessions       │
│                            │  + Multi-agent routing       │
│                            │  + Gateway & fan-out         │
│                            │  + Multi-tenancy             │
│                            │  + HTTP API & CLI            │
│                            │  + Hooks & policies          │
└──────────────────────────────────────────────────────────┘
```

## What Karta provides

| Feature | Description |
|---------|-------------|
| **Multi-agent routing** | Discover and route to specialist agents defined in your harness's native format |
| **Multi-user sessions** | Route conversations by metadata (customer ID, channel, etc.) with automatic persistence |
| **Participant model** | Multiple humans and AI agents in the same session with message attribution |
| **Gateway & fan-out** | Unified event ingestion with fan-out delivery to all session participants |
| **Cross-instance messaging** | Agents on different Karta instances communicate via gateway HTTP POST |
| **Multi-tenancy** | Workspace-per-user isolation with `KartaHub` orchestrator |
| **Session persistence** | SQLite (default), PostgreSQL, or S3 backends |
| **Lifecycle hooks** | Events on `message.received`, `message.completed`, `agent.handoff`, `session.created` |
| **Policy enforcement** | Validate messages against configurable policies (length limits, message counts, keyword gates) |
| **HTTP API** | Production-ready FastAPI server with REST endpoints and SSE streaming |
| **Internal CLI** | `karta-runtime dev/dev-serve/serve` - streaming terminal REPL and the local/self-host serve planes (the public CLI is `@karta.sh/cli`) |
| **Typed streaming** | Structured events: `text`, `tool_use`, `reasoning`, `step_start`, `step_finish`, `error`, `input_required` |

## Install

```bash
pip install karta-runtime
```

With optional backends:

```bash
pip install karta-runtime[postgres]   # PostgreSQL sessions
pip install karta-runtime[s3]         # S3 sessions
```

You also need a coding agent harness installed:

- **Claude Code**: `npm install -g @anthropic-ai/claude-code` ([docs](https://docs.anthropic.com/en/docs/claude-code))
- **OpenCode**: `curl -fsSL https://opencode.ai/install | bash` ([docs](https://opencode.ai))

## Quickstart

### Zero-config hello world

```python
from karta import Karta

app = Karta()
response = app.send_sync("Hello!")
print(response.text)
```

Karta auto-detects your harness from the project directory (`.claude/` → Claude Code, `.opencode/` → OpenCode).

### Multi-turn sessions

```python
from karta import Karta

app = Karta()

session = app.session(metadata={"customer_id": "abc123"})
response = session.send_sync("I need help with my order")
response = session.send_sync("Order #12345")

# Resume later by looking up the session
session = app.session(metadata={"customer_id": "abc123"})
response = session.send_sync("Any updates?")
```

### Multi-agent routing

Define specialist agents in your harness's native format (`.claude/agents/*.md` or `.opencode/agents/*.md`), then route:

```python
from karta import Karta

app = Karta()

# Route to a specific agent
response = app.send_sync("Audit my billing", agent="billing-specialist")

# Agent handoff within a session
session = app.session(metadata={"customer_id": "abc123"})
session.send_sync("I need help with my order")         # → default agent
session.current_agent = app.agents["billing"]           # handoff
session.send_sync("Check invoice #789")                 # → billing agent
```

### Multi-participant sessions

```python
from karta import Karta, HumanAgent

app = Karta()
session = app.session()

alice = HumanAgent(name="alice", display_name="Alice Chen")
bob = HumanAgent(name="bob", display_name="Bob Park")

# Messages are attributed to the sending participant
session.send_sync("I need help with deployment", participant=alice)
session.send_sync("I can help — what's the error?", participant=bob)
```

### Streaming

```python
import asyncio
from karta import Karta

async def main():
    app = Karta()
    async for event in app.stream("Explain quicksort"):
        if event.type == "text":
            print(event.text, end="", flush=True)

asyncio.run(main())
```

### HTTP API

```python
from karta import Karta
from karta.server import create_fastapi_app
import uvicorn

app = Karta()
fastapi_app = create_fastapi_app(app)
uvicorn.run(fastapi_app, host="0.0.0.0", port=8000)
```

This exposes:

- `POST /v1/send` — send a message, get a response
- `POST /v1/stream` — send a message, get SSE stream
- `POST /v1/sessions` — create a session
- `GET /v1/sessions` — list/lookup sessions
- `POST /v1/sessions/{id}/messages` — send within a session
- `POST /v1/sessions/{id}/input/respond` — respond to approval prompts
- `POST /v1/gateway/submit` — submit a gateway event
- `POST /v1/gateway/deliver` — deliver to a local participant
- `GET /healthz` — health check

### Multi-tenancy

```python
from karta import KartaHub

hub = KartaHub("/path/to/karta-root")

# Each tenant/user gets an isolated workspace
session = hub.session("acme", "alice", metadata={"topic": "billing"})
response = session.send_sync("Help with invoice")
```

### Lifecycle hooks

```python
app = Karta()

@app.on("message.completed")
async def log_response(event):
    print(f"Session {event.session.id}: {event.message.text}")

@app.on("agent.handoff")
async def track_handoff(event):
    print(f"Handoff: {event.payload['from']} → {event.payload['to']}")
```

### CLI (internal)

The customer-facing CLI is `@karta.sh/cli`; this package's verbs are internal
(local platform dev, self-host):

```bash
karta-runtime dev <path>         # Hot-reload REPL against a folder
karta-runtime dev-serve <path>   # Serve a folder behind the consumer session API
                                 # (what the unified CLI's `karta dev` spawns)
karta-runtime serve              # The platform serve plane (self-host / dev-infra)
```

This package installs no `karta` script at all - that name belongs to
the unified CLI (`npm install -g @karta.sh/cli`). It was dropped rather
than shimmed: karta-python never shipped to PyPI, so there is no
installed base to point anywhere.

## Architecture

```
                 External Clients / Other Karta Instances
                              │
                    ┌─────────▼──────────┐
                    │     Gateway         │  event ingestion, fan-out delivery
                    │  Local · HTTP       │  cross-instance messaging
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Client Layer      │  HTTP API · CLI · Python SDK
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Multi-Tenancy     │  KartaHub → WorkspaceManager
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │    Karta Core       │  sessions, agents, policies,
                    │                     │  hooks, participants
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Harness Layer     │  Claude Code (SDK) or
                    │                     │  OpenCode (CLI subprocess)
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Coding Agent      │  tools, MCP, context,
                    │                     │  memory, skills
                    └──────────────────────┘
```

### Design principles

- **Convention over configuration** — follows your harness's folder conventions
- **Progressive disclosure** — start with 3 lines, add features as you need them
- **Harness-native** — agents are defined in `.claude/agents/*.md` or `.opencode/agents/*.md`, not reinvented
- **Zero abstraction tax** — examples from harness docs work as-is inside Karta

## Progressive examples

The [`examples/`](examples/) directory walks through increasing levels of complexity:

| Level | Directory | What it demonstrates |
|-------|-----------|---------------------|
| 0 | `level-0-zero-config/` | No config needed — just `app.send()` |
| 1 | `level-1-project-context/` | Project context with `AGENTS.md` / `.opencode` |
| 1 | `level-1-project-context-claude-code/` | Same, using Claude Code |
| 2 | `level-2-custom-agent/` | Single agent with a custom skill |
| 2 | `level-2-custom-agent-claude-code/` | Same, using Claude Code |
| 3 | `level-3-multiple-agents/` | Multi-agent routing |
| 4 | `level-4-multi-turn-sessions/` | Session persistence and metadata lookup |
| 5 | `level-5-hooks-policies/` | Lifecycle hooks and policy enforcement |

## Configuration

Karta uses your harness's native agent definitions as the source of truth. Optional Karta-specific settings go in `karta.jsonc`:

```jsonc
{
  "cli": {
    "hidden_event_types": ["system"],
    "input_required_policy": "prompt"
  },
  "harness": {
    "claude": {
      "idle_timeout_seconds": 600,
      "permission_intercept": false
    }
  }
}
```

See [`examples/configurations/`](examples/configurations/) for copy-ready templates.

## Supported harnesses

| Harness | Adapter | Detection |
|---------|---------|-----------|
| Claude Code | `ClaudeAdapter` (via Claude SDK) | `.claude/` directory or `CLAUDE.md` |
| OpenCode | `OpenCodeAdapter` (via `opencode run`) | `.opencode/` directory |
| Deep Agents Code | `DeepAgentsAdapter` (via `dcode -n`) | `.deepagents/` directory |
| Goose | `GooseAdapter` (via `goose run --output-format stream-json`) | `.goose/` directory |
| Codex CLI | `CodexCliAdapter` (via `codex exec --json`) | `.codex/config.toml` |

Adding a new harness means implementing one `HarnessAdapter` class.

## Documentation

Design documents and implementation specs live in [`dev/`](dev/):

- [Architecture](dev/ARCHITECTURE.md) — system architecture reference
- [Design document](dev/2026-02-12-karta-design-doc.md) — architecture and design philosophy
- [Implementation spec](dev/2026-02-13-karta-implementation-spec.md) — detailed implementation reference
- [CLI spec](dev/2026-02-13-karta-cli.md) — CLI commands and options
- [HTTP API spec](dev/2026-02-13-karta-http-api.md) — REST endpoint reference
- [Gateway implementation plan](dev/2026-02-14-gateway-implementation-plan.md) — gateway system design
- [Multi-tenancy architecture](dev/2026-02-14-multi-tenancy-architecture.md) — workspace isolation deep dive
- [Phase status](dev/phase-status.md) — implementation progress tracking

## Development

```bash
# Install dependencies
poetry install --all-extras

# Run tests
poetry run pytest

# Lint
poetry run ruff check src/ tests/

# Type check
poetry run mypy src/karta/
```

## License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.

