karta-runtime 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- karta_runtime-0.1.0/PKG-INFO +396 -0
- karta_runtime-0.1.0/README.md +347 -0
- karta_runtime-0.1.0/pyproject.toml +116 -0
- karta_runtime-0.1.0/src/karta/__init__.py +48 -0
- karta_runtime-0.1.0/src/karta/__main__.py +4 -0
- karta_runtime-0.1.0/src/karta/active_releases.py +129 -0
- karta_runtime-0.1.0/src/karta/agent.py +59 -0
- karta_runtime-0.1.0/src/karta/app.py +672 -0
- karta_runtime-0.1.0/src/karta/billing/__init__.py +13 -0
- karta_runtime-0.1.0/src/karta/billing/usage_emitter.py +416 -0
- karta_runtime-0.1.0/src/karta/builder.py +223 -0
- karta_runtime-0.1.0/src/karta/byok.py +206 -0
- karta_runtime-0.1.0/src/karta/cache.py +257 -0
- karta_runtime-0.1.0/src/karta/cli.py +609 -0
- karta_runtime-0.1.0/src/karta/cli_renderer.py +173 -0
- karta_runtime-0.1.0/src/karta/consumer/__init__.py +7 -0
- karta_runtime-0.1.0/src/karta/consumer/challenge.py +116 -0
- karta_runtime-0.1.0/src/karta/consumer/embed.py +310 -0
- karta_runtime-0.1.0/src/karta/consumer/event_log.py +80 -0
- karta_runtime-0.1.0/src/karta/consumer/events.py +34 -0
- karta_runtime-0.1.0/src/karta/consumer/managed_agents.py +66 -0
- karta_runtime-0.1.0/src/karta/consumer/openai_chat.py +97 -0
- karta_runtime-0.1.0/src/karta/consumer/openai_responses.py +116 -0
- karta_runtime-0.1.0/src/karta/consumer/project_origins.py +98 -0
- karta_runtime-0.1.0/src/karta/consumer/session_token.py +78 -0
- karta_runtime-0.1.0/src/karta/control_plane.py +140 -0
- karta_runtime-0.1.0/src/karta/durable/__init__.py +22 -0
- karta_runtime-0.1.0/src/karta/durable/local.py +34 -0
- karta_runtime-0.1.0/src/karta/durable/port.py +19 -0
- karta_runtime-0.1.0/src/karta/durable/s3.py +64 -0
- karta_runtime-0.1.0/src/karta/events.py +21 -0
- karta_runtime-0.1.0/src/karta/execution/__init__.py +22 -0
- karta_runtime-0.1.0/src/karta/execution/fake.py +78 -0
- karta_runtime-0.1.0/src/karta/execution/local.py +96 -0
- karta_runtime-0.1.0/src/karta/execution/port.py +85 -0
- karta_runtime-0.1.0/src/karta/gateway/__init__.py +15 -0
- karta_runtime-0.1.0/src/karta/gateway/base.py +29 -0
- karta_runtime-0.1.0/src/karta/gateway/events.py +73 -0
- karta_runtime-0.1.0/src/karta/gateway/http.py +80 -0
- karta_runtime-0.1.0/src/karta/gateway/local.py +151 -0
- karta_runtime-0.1.0/src/karta/gateway/registry.py +65 -0
- karta_runtime-0.1.0/src/karta/harness/__init__.py +4 -0
- karta_runtime-0.1.0/src/karta/harness/base.py +142 -0
- karta_runtime-0.1.0/src/karta/harness/claude.py +974 -0
- karta_runtime-0.1.0/src/karta/harness/claude_message_mapper.py +418 -0
- karta_runtime-0.1.0/src/karta/harness/factory.py +37 -0
- karta_runtime-0.1.0/src/karta/harness/opencode.py +592 -0
- karta_runtime-0.1.0/src/karta/harness/utils.py +45 -0
- karta_runtime-0.1.0/src/karta/hub.py +126 -0
- karta_runtime-0.1.0/src/karta/instance.py +729 -0
- karta_runtime-0.1.0/src/karta/model_settings.py +134 -0
- karta_runtime-0.1.0/src/karta/observability/__init__.py +156 -0
- karta_runtime-0.1.0/src/karta/observability/_noop.py +75 -0
- karta_runtime-0.1.0/src/karta/observability/_otel.py +81 -0
- karta_runtime-0.1.0/src/karta/observability/logging_setup.py +96 -0
- karta_runtime-0.1.0/src/karta/observability/metrics.py +74 -0
- karta_runtime-0.1.0/src/karta/observability/secret_redaction.py +96 -0
- karta_runtime-0.1.0/src/karta/participant.py +55 -0
- karta_runtime-0.1.0/src/karta/persistence/__init__.py +46 -0
- karta_runtime-0.1.0/src/karta/persistence/gc.py +164 -0
- karta_runtime-0.1.0/src/karta/persistence/local_backend.py +128 -0
- karta_runtime-0.1.0/src/karta/persistence/manifest.py +225 -0
- karta_runtime-0.1.0/src/karta/persistence/profile.py +156 -0
- karta_runtime-0.1.0/src/karta/persistence/reconcile.py +76 -0
- karta_runtime-0.1.0/src/karta/persistence/s3_backend.py +131 -0
- karta_runtime-0.1.0/src/karta/persistence/store.py +297 -0
- karta_runtime-0.1.0/src/karta/persistence/text_merge.py +70 -0
- karta_runtime-0.1.0/src/karta/policies.py +29 -0
- karta_runtime-0.1.0/src/karta/project_runtime.py +201 -0
- karta_runtime-0.1.0/src/karta/registry.py +137 -0
- karta_runtime-0.1.0/src/karta/release_artifacts.py +70 -0
- karta_runtime-0.1.0/src/karta/releases.py +478 -0
- karta_runtime-0.1.0/src/karta/response.py +150 -0
- karta_runtime-0.1.0/src/karta/runtime/__init__.py +3 -0
- karta_runtime-0.1.0/src/karta/runtime/turn_accumulator.py +146 -0
- karta_runtime-0.1.0/src/karta/secrets_bootstrap.py +88 -0
- karta_runtime-0.1.0/src/karta/server/__init__.py +3 -0
- karta_runtime-0.1.0/src/karta/server/agentcore.py +393 -0
- karta_runtime-0.1.0/src/karta/server/agentcore_client.py +481 -0
- karta_runtime-0.1.0/src/karta/server/agentcore_project_runtime.py +210 -0
- karta_runtime-0.1.0/src/karta/server/agentcore_router.py +118 -0
- karta_runtime-0.1.0/src/karta/server/agentcore_serve.py +116 -0
- karta_runtime-0.1.0/src/karta/server/auth.py +625 -0
- karta_runtime-0.1.0/src/karta/server/credential_guard.py +51 -0
- karta_runtime-0.1.0/src/karta/server/fastapi_app.py +2454 -0
- karta_runtime-0.1.0/src/karta/server/instance_routes.py +199 -0
- karta_runtime-0.1.0/src/karta/server/serve_surfaces.py +231 -0
- karta_runtime-0.1.0/src/karta/server/session_store.py +220 -0
- karta_runtime-0.1.0/src/karta/server/sse.py +10 -0
- karta_runtime-0.1.0/src/karta/session.py +161 -0
- karta_runtime-0.1.0/src/karta/vault/__init__.py +21 -0
- karta_runtime-0.1.0/src/karta/vault/agentcore.py +33 -0
- karta_runtime-0.1.0/src/karta/vault/local.py +43 -0
- karta_runtime-0.1.0/src/karta/vault/port.py +28 -0
- karta_runtime-0.1.0/src/karta/workspace.py +489 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: karta-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Karta agent runtime: harness adapters, dev serve, and the platform serve layer
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: agents,ai,framework,orchestration
|
|
7
|
+
Author: Karta
|
|
8
|
+
Author-email: team@karta.sh
|
|
9
|
+
Requires-Python: >=3.9,<4.0
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Provides-Extra: dev-reload
|
|
21
|
+
Provides-Extra: gitmerge
|
|
22
|
+
Provides-Extra: otel
|
|
23
|
+
Provides-Extra: postgres
|
|
24
|
+
Provides-Extra: s3
|
|
25
|
+
Requires-Dist: anyio (>=4.8.0,<5.0.0)
|
|
26
|
+
Requires-Dist: boto3 (>=1.35.92,<2.0.0) ; extra == "s3"
|
|
27
|
+
Requires-Dist: claude-agent-sdk (>=0.2.82,<0.3.0) ; python_version >= "3.10"
|
|
28
|
+
Requires-Dist: fastapi (>=0.115.6,<0.116.0)
|
|
29
|
+
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
30
|
+
Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0) ; extra == "otel"
|
|
31
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra == "otel"
|
|
32
|
+
Requires-Dist: opentelemetry-instrumentation-asgi (>=0.48b0,<0.49) ; extra == "otel"
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.48b0,<0.49) ; extra == "otel"
|
|
34
|
+
Requires-Dist: opentelemetry-instrumentation-httpx (>=0.48b0,<0.49) ; extra == "otel"
|
|
35
|
+
Requires-Dist: opentelemetry-sdk (>=1.27.0,<2.0.0) ; extra == "otel"
|
|
36
|
+
Requires-Dist: psycopg[binary] (>=3.2.3,<4.0.0) ; extra == "postgres"
|
|
37
|
+
Requires-Dist: pydantic (>=2.10.4,<3.0.0)
|
|
38
|
+
Requires-Dist: pygit2 (>=1.18.0,<2.0.0) ; (python_version >= "3.11") and (extra == "gitmerge")
|
|
39
|
+
Requires-Dist: python-frontmatter (>=1.1.0,<2.0.0)
|
|
40
|
+
Requires-Dist: rich (>=13.0.0,<16.0.0)
|
|
41
|
+
Requires-Dist: typer (>=0.21.0,<0.22.0)
|
|
42
|
+
Requires-Dist: uvicorn[standard] (>=0.32.1,<0.40.0)
|
|
43
|
+
Requires-Dist: watchfiles (>=1.0.0,<2.0.0) ; extra == "dev-reload"
|
|
44
|
+
Project-URL: Documentation, https://docs.karta.sh
|
|
45
|
+
Project-URL: Homepage, https://karta.sh
|
|
46
|
+
Project-URL: Repository, https://github.com/karta-sh/karta
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
|
|
49
|
+
<div align="center">
|
|
50
|
+
<h1>karta-runtime</h1>
|
|
51
|
+
<p><strong>The Karta runtime: harness adapters, sessions, and the consumer session API on agent harnesses like Claude Code and OpenCode</strong></p>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div align="center">
|
|
55
|
+
|
|
56
|
+
[](https://github.com/karta/karta/blob/main/LICENSE)
|
|
57
|
+
[](https://pypi.org/project/karta-runtime/)
|
|
58
|
+
[](https://www.python.org/)
|
|
59
|
+
[](https://github.com/karta/karta/issues)
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
> **Looking for the `karta` command?** The public CLI is
|
|
64
|
+
> [`@karta.sh/cli`](../../sdks/typescript-cli/) (`npm install -g @karta.sh/cli`).
|
|
65
|
+
> This package is `karta-runtime` - the internal engine that CLI bootstraps
|
|
66
|
+
> for `karta dev`, and the data plane the platform serves (RFC 0013,
|
|
67
|
+
> [docs/rfcs/0013-unified-cli.md](../../docs/rfcs/0013-unified-cli.md)). Its
|
|
68
|
+
> own CLI verbs are internal (see [CLI](#cli-internal)); use it directly as a
|
|
69
|
+
> Python SDK/library, exactly as documented below.
|
|
70
|
+
|
|
71
|
+
## Why Karta
|
|
72
|
+
|
|
73
|
+
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.
|
|
74
|
+
|
|
75
|
+
**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.
|
|
76
|
+
|
|
77
|
+
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.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
┌──────────────────────────────────────────────────────────┐
|
|
81
|
+
│ Other frameworks │ Karta │
|
|
82
|
+
│ │ │
|
|
83
|
+
│ Build agents from scratch │ Build ON existing harnesses │
|
|
84
|
+
│ Own tool system │ Harness tools (MCP, etc.) │
|
|
85
|
+
│ Own memory/context │ Harness memory/context │
|
|
86
|
+
│ Own execution loop │ Harness execution loop │
|
|
87
|
+
│ + Multi-agent orchestr. │ + Multi-user sessions │
|
|
88
|
+
│ │ + Multi-agent routing │
|
|
89
|
+
│ │ + Gateway & fan-out │
|
|
90
|
+
│ │ + Multi-tenancy │
|
|
91
|
+
│ │ + HTTP API & CLI │
|
|
92
|
+
│ │ + Hooks & policies │
|
|
93
|
+
└──────────────────────────────────────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## What Karta provides
|
|
97
|
+
|
|
98
|
+
| Feature | Description |
|
|
99
|
+
|---------|-------------|
|
|
100
|
+
| **Multi-agent routing** | Discover and route to specialist agents defined in your harness's native format |
|
|
101
|
+
| **Multi-user sessions** | Route conversations by metadata (customer ID, channel, etc.) with automatic persistence |
|
|
102
|
+
| **Participant model** | Multiple humans and AI agents in the same session with message attribution |
|
|
103
|
+
| **Gateway & fan-out** | Unified event ingestion with fan-out delivery to all session participants |
|
|
104
|
+
| **Cross-instance messaging** | Agents on different Karta instances communicate via gateway HTTP POST |
|
|
105
|
+
| **Multi-tenancy** | Workspace-per-user isolation with `KartaHub` orchestrator |
|
|
106
|
+
| **Session persistence** | SQLite (default), PostgreSQL, or S3 backends |
|
|
107
|
+
| **Lifecycle hooks** | Events on `message.received`, `message.completed`, `agent.handoff`, `session.created` |
|
|
108
|
+
| **Policy enforcement** | Validate messages against configurable policies (length limits, message counts, keyword gates) |
|
|
109
|
+
| **HTTP API** | Production-ready FastAPI server with REST endpoints and SSE streaming |
|
|
110
|
+
| **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`) |
|
|
111
|
+
| **Typed streaming** | Structured events: `text`, `tool_use`, `reasoning`, `step_start`, `step_finish`, `error`, `input_required` |
|
|
112
|
+
|
|
113
|
+
## Install
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pip install karta-runtime
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
With optional backends:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pip install karta-runtime[postgres] # PostgreSQL sessions
|
|
123
|
+
pip install karta-runtime[s3] # S3 sessions
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
You also need a coding agent harness installed:
|
|
127
|
+
|
|
128
|
+
- **Claude Code**: `npm install -g @anthropic-ai/claude-code` ([docs](https://docs.anthropic.com/en/docs/claude-code))
|
|
129
|
+
- **OpenCode**: `curl -fsSL https://opencode.ai/install | bash` ([docs](https://opencode.ai))
|
|
130
|
+
|
|
131
|
+
## Quickstart
|
|
132
|
+
|
|
133
|
+
### Zero-config hello world
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from karta import Karta
|
|
137
|
+
|
|
138
|
+
app = Karta()
|
|
139
|
+
response = app.send_sync("Hello!")
|
|
140
|
+
print(response.text)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Karta auto-detects your harness from the project directory (`.claude/` → Claude Code, `.opencode/` → OpenCode).
|
|
144
|
+
|
|
145
|
+
### Multi-turn sessions
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from karta import Karta
|
|
149
|
+
|
|
150
|
+
app = Karta()
|
|
151
|
+
|
|
152
|
+
session = app.session(metadata={"customer_id": "abc123"})
|
|
153
|
+
response = session.send_sync("I need help with my order")
|
|
154
|
+
response = session.send_sync("Order #12345")
|
|
155
|
+
|
|
156
|
+
# Resume later by looking up the session
|
|
157
|
+
session = app.session(metadata={"customer_id": "abc123"})
|
|
158
|
+
response = session.send_sync("Any updates?")
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Multi-agent routing
|
|
162
|
+
|
|
163
|
+
Define specialist agents in your harness's native format (`.claude/agents/*.md` or `.opencode/agents/*.md`), then route:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from karta import Karta
|
|
167
|
+
|
|
168
|
+
app = Karta()
|
|
169
|
+
|
|
170
|
+
# Route to a specific agent
|
|
171
|
+
response = app.send_sync("Audit my billing", agent="billing-specialist")
|
|
172
|
+
|
|
173
|
+
# Agent handoff within a session
|
|
174
|
+
session = app.session(metadata={"customer_id": "abc123"})
|
|
175
|
+
session.send_sync("I need help with my order") # → default agent
|
|
176
|
+
session.current_agent = app.agents["billing"] # handoff
|
|
177
|
+
session.send_sync("Check invoice #789") # → billing agent
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Multi-participant sessions
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from karta import Karta, HumanAgent
|
|
184
|
+
|
|
185
|
+
app = Karta()
|
|
186
|
+
session = app.session()
|
|
187
|
+
|
|
188
|
+
alice = HumanAgent(name="alice", display_name="Alice Chen")
|
|
189
|
+
bob = HumanAgent(name="bob", display_name="Bob Park")
|
|
190
|
+
|
|
191
|
+
# Messages are attributed to the sending participant
|
|
192
|
+
session.send_sync("I need help with deployment", participant=alice)
|
|
193
|
+
session.send_sync("I can help — what's the error?", participant=bob)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Streaming
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
import asyncio
|
|
200
|
+
from karta import Karta
|
|
201
|
+
|
|
202
|
+
async def main():
|
|
203
|
+
app = Karta()
|
|
204
|
+
async for event in app.stream("Explain quicksort"):
|
|
205
|
+
if event.type == "text":
|
|
206
|
+
print(event.text, end="", flush=True)
|
|
207
|
+
|
|
208
|
+
asyncio.run(main())
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### HTTP API
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from karta import Karta
|
|
215
|
+
from karta.server import create_fastapi_app
|
|
216
|
+
import uvicorn
|
|
217
|
+
|
|
218
|
+
app = Karta()
|
|
219
|
+
fastapi_app = create_fastapi_app(app)
|
|
220
|
+
uvicorn.run(fastapi_app, host="0.0.0.0", port=8000)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
This exposes:
|
|
224
|
+
|
|
225
|
+
- `POST /v1/send` — send a message, get a response
|
|
226
|
+
- `POST /v1/stream` — send a message, get SSE stream
|
|
227
|
+
- `POST /v1/sessions` — create a session
|
|
228
|
+
- `GET /v1/sessions` — list/lookup sessions
|
|
229
|
+
- `POST /v1/sessions/{id}/messages` — send within a session
|
|
230
|
+
- `POST /v1/sessions/{id}/input/respond` — respond to approval prompts
|
|
231
|
+
- `POST /v1/gateway/submit` — submit a gateway event
|
|
232
|
+
- `POST /v1/gateway/deliver` — deliver to a local participant
|
|
233
|
+
- `GET /healthz` — health check
|
|
234
|
+
|
|
235
|
+
### Multi-tenancy
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
from karta import KartaHub
|
|
239
|
+
|
|
240
|
+
hub = KartaHub("/path/to/karta-root")
|
|
241
|
+
|
|
242
|
+
# Each tenant/user gets an isolated workspace
|
|
243
|
+
session = hub.session("acme", "alice", metadata={"topic": "billing"})
|
|
244
|
+
response = session.send_sync("Help with invoice")
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Lifecycle hooks
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
app = Karta()
|
|
251
|
+
|
|
252
|
+
@app.on("message.completed")
|
|
253
|
+
async def log_response(event):
|
|
254
|
+
print(f"Session {event.session.id}: {event.message.text}")
|
|
255
|
+
|
|
256
|
+
@app.on("agent.handoff")
|
|
257
|
+
async def track_handoff(event):
|
|
258
|
+
print(f"Handoff: {event.payload['from']} → {event.payload['to']}")
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### CLI (internal)
|
|
262
|
+
|
|
263
|
+
The customer-facing CLI is `@karta.sh/cli`; this package's verbs are internal
|
|
264
|
+
(local platform dev, self-host):
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
karta-runtime dev <path> # Hot-reload REPL against a folder
|
|
268
|
+
karta-runtime dev-serve <path> # Serve a folder behind the consumer session API
|
|
269
|
+
# (what the unified CLI's `karta dev` spawns)
|
|
270
|
+
karta-runtime serve # The platform serve plane (self-host / dev-infra)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This package installs no `karta` script at all - that name belongs to
|
|
274
|
+
the unified CLI (`npm install -g @karta.sh/cli`). It was dropped rather
|
|
275
|
+
than shimmed: karta-python never shipped to PyPI, so there is no
|
|
276
|
+
installed base to point anywhere.
|
|
277
|
+
|
|
278
|
+
## Architecture
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
External Clients / Other Karta Instances
|
|
282
|
+
│
|
|
283
|
+
┌─────────▼──────────┐
|
|
284
|
+
│ Gateway │ event ingestion, fan-out delivery
|
|
285
|
+
│ Local · HTTP │ cross-instance messaging
|
|
286
|
+
└─────────┬──────────┘
|
|
287
|
+
│
|
|
288
|
+
┌─────────▼──────────┐
|
|
289
|
+
│ Client Layer │ HTTP API · CLI · Python SDK
|
|
290
|
+
└─────────┬──────────┘
|
|
291
|
+
│
|
|
292
|
+
┌─────────▼──────────┐
|
|
293
|
+
│ Multi-Tenancy │ KartaHub → WorkspaceManager
|
|
294
|
+
└─────────┬──────────┘
|
|
295
|
+
│
|
|
296
|
+
┌─────────▼──────────┐
|
|
297
|
+
│ Karta Core │ sessions, agents, policies,
|
|
298
|
+
│ │ hooks, participants
|
|
299
|
+
└─────────┬──────────┘
|
|
300
|
+
│
|
|
301
|
+
┌─────────▼──────────┐
|
|
302
|
+
│ Harness Layer │ Claude Code (SDK) or
|
|
303
|
+
│ │ OpenCode (CLI subprocess)
|
|
304
|
+
└─────────┬──────────┘
|
|
305
|
+
│
|
|
306
|
+
┌─────────▼──────────┐
|
|
307
|
+
│ Coding Agent │ tools, MCP, context,
|
|
308
|
+
│ │ memory, skills
|
|
309
|
+
└──────────────────────┘
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Design principles
|
|
313
|
+
|
|
314
|
+
- **Convention over configuration** — follows your harness's folder conventions
|
|
315
|
+
- **Progressive disclosure** — start with 3 lines, add features as you need them
|
|
316
|
+
- **Harness-native** — agents are defined in `.claude/agents/*.md` or `.opencode/agents/*.md`, not reinvented
|
|
317
|
+
- **Zero abstraction tax** — examples from harness docs work as-is inside Karta
|
|
318
|
+
|
|
319
|
+
## Progressive examples
|
|
320
|
+
|
|
321
|
+
The [`examples/`](examples/) directory walks through increasing levels of complexity:
|
|
322
|
+
|
|
323
|
+
| Level | Directory | What it demonstrates |
|
|
324
|
+
|-------|-----------|---------------------|
|
|
325
|
+
| 0 | `level-0-zero-config/` | No config needed — just `app.send()` |
|
|
326
|
+
| 1 | `level-1-project-context/` | Project context with `AGENTS.md` / `.opencode` |
|
|
327
|
+
| 1 | `level-1-project-context-claude-code/` | Same, using Claude Code |
|
|
328
|
+
| 2 | `level-2-custom-agent/` | Single agent with a custom skill |
|
|
329
|
+
| 2 | `level-2-custom-agent-claude-code/` | Same, using Claude Code |
|
|
330
|
+
| 3 | `level-3-multiple-agents/` | Multi-agent routing |
|
|
331
|
+
| 4 | `level-4-multi-turn-sessions/` | Session persistence and metadata lookup |
|
|
332
|
+
| 5 | `level-5-hooks-policies/` | Lifecycle hooks and policy enforcement |
|
|
333
|
+
|
|
334
|
+
## Configuration
|
|
335
|
+
|
|
336
|
+
Karta uses your harness's native agent definitions as the source of truth. Optional Karta-specific settings go in `karta.jsonc`:
|
|
337
|
+
|
|
338
|
+
```jsonc
|
|
339
|
+
{
|
|
340
|
+
"cli": {
|
|
341
|
+
"hidden_event_types": ["system"],
|
|
342
|
+
"input_required_policy": "prompt"
|
|
343
|
+
},
|
|
344
|
+
"harness": {
|
|
345
|
+
"claude": {
|
|
346
|
+
"idle_timeout_seconds": 600,
|
|
347
|
+
"permission_intercept": false
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
See [`examples/configurations/`](examples/configurations/) for copy-ready templates.
|
|
354
|
+
|
|
355
|
+
## Supported harnesses
|
|
356
|
+
|
|
357
|
+
| Harness | Adapter | Detection |
|
|
358
|
+
|---------|---------|-----------|
|
|
359
|
+
| Claude Code | `ClaudeAdapter` (via Claude SDK) | `.claude/` directory or `CLAUDE.md` |
|
|
360
|
+
| OpenCode | `OpenCodeAdapter` (via `opencode run`) | `.opencode/` directory |
|
|
361
|
+
|
|
362
|
+
Adding a new harness means implementing one `HarnessAdapter` class.
|
|
363
|
+
|
|
364
|
+
## Documentation
|
|
365
|
+
|
|
366
|
+
Design documents and implementation specs live in [`dev/`](dev/):
|
|
367
|
+
|
|
368
|
+
- [Architecture](dev/ARCHITECTURE.md) — system architecture reference
|
|
369
|
+
- [Design document](dev/2026-02-12-karta-design-doc.md) — architecture and design philosophy
|
|
370
|
+
- [Implementation spec](dev/2026-02-13-karta-implementation-spec.md) — detailed implementation reference
|
|
371
|
+
- [CLI spec](dev/2026-02-13-karta-cli.md) — CLI commands and options
|
|
372
|
+
- [HTTP API spec](dev/2026-02-13-karta-http-api.md) — REST endpoint reference
|
|
373
|
+
- [Gateway implementation plan](dev/2026-02-14-gateway-implementation-plan.md) — gateway system design
|
|
374
|
+
- [Multi-tenancy architecture](dev/2026-02-14-multi-tenancy-architecture.md) — workspace isolation deep dive
|
|
375
|
+
- [Phase status](dev/phase-status.md) — implementation progress tracking
|
|
376
|
+
|
|
377
|
+
## Development
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
# Install dependencies
|
|
381
|
+
poetry install --all-extras
|
|
382
|
+
|
|
383
|
+
# Run tests
|
|
384
|
+
poetry run pytest
|
|
385
|
+
|
|
386
|
+
# Lint
|
|
387
|
+
poetry run ruff check src/ tests/
|
|
388
|
+
|
|
389
|
+
# Type check
|
|
390
|
+
poetry run mypy src/karta/
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## License
|
|
394
|
+
|
|
395
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|
|
396
|
+
|