Metadata-Version: 2.4
Name: kora-agent
Version: 0.1.0
Summary: A lightweight Agent framework with extensible model providers
Author: xvshiting
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.12
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: all
Requires-Dist: anthropic>=0.25.0; extra == 'all'
Requires-Dist: httpx>=0.25.0; extra == 'all'
Requires-Dist: kora-code>=0.1.0; extra == 'all'
Requires-Dist: mypy>=1.8.0; extra == 'all'
Requires-Dist: openai>=1.0.0; extra == 'all'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
Requires-Dist: pytest>=8.0.0; extra == 'all'
Requires-Dist: ruff>=0.3.0; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.25.0; extra == 'anthropic'
Provides-Extra: code
Requires-Dist: kora-code>=0.1.0; extra == 'code'
Provides-Extra: dev
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.3.0; extra == 'dev'
Provides-Extra: network
Requires-Dist: httpx>=0.25.0; extra == 'network'
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == 'openai'
Description-Content-Type: text/markdown

<p align="center">
  <img src="assets/branding/logo.png" alt="Kora" width="420">
</p>

<h3 align="center">A lightweight, layered Agent framework for Python</h3>

<p align="center">
  <a href="https://www.python.org/downloads/"><img alt="Python" src="https://img.shields.io/badge/python-3.12+-blue.svg"></a>
  <a href="https://opensource.org/licenses/MIT"><img alt="License" src="https://img.shields.io/badge/License-MIT-yellow.svg"></a>
  <img alt="Status" src="https://img.shields.io/badge/status-alpha-orange.svg">
  <img alt="Type checked" src="https://img.shields.io/badge/typed-mypy-blue.svg">
  <img alt="Code style" src="https://img.shields.io/badge/code%20style-ruff-000000.svg">
</p>

---

Kora is a lightweight Agent framework built around a strict three-layer
architecture: **Kernel → Runtime → Host**. It is designed to absorb common
agent complexity—model-tool loops, session state, workspace isolation,
event observability—so that authors can define agents with minimal code
while retaining full control over execution.

A minimal agent is just an `AGENT.md` file plus a handful of `@tool`
functions. The official Kora Code Agent runs on the same public APIs
available to every external developer—no privileged branches, no hidden
hooks.

## Table of Contents

- [Highlights](#highlights)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Built-in Tools](#built-in-tools)
- [Model Providers](#model-providers)
- [Architecture](#architecture)
- [Examples](#examples)
- [Documentation](#documentation)
- [Development](#development)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [License](#license)

## Highlights

- **Small public API.** Everyday work needs only `Agent`, `Session`,
  `tool`, and `run`. Kernel/Runtime internals stay out of the way.
- **Layered architecture.** Kernel runs one synchronous model-tool loop;
  Runtime manages async Agent/Session/Run semantics; Host handles
  persistence, identity, and permissions. Dependencies point inward.
- **Extensible model providers.** Built-in provider specs cover OpenAI,
  Anthropic, DashScope, JDCloud, DeepSeek, Moonshot, OpenRouter, and
  Ollama. Providers are resolved through a registry and communicate via
  pluggable API protocols such as OpenAI Completions and Anthropic Messages.
- **Rich built-in tools.** Filesystem, text processing, shell, network,
  and sandboxed Python execution—each with workspace boundaries.
- **Security by code, not by prompt.** SSRF protection, command
  filtering, import restrictions, and workspace isolation are enforced
  in implementation, not just in prompts.
- **Observable runs.** Every Run emits structured events
  (`RunStarted`, `ToolExecuted`, `RunCompleted`, …) for streaming and
  debugging.
- **Independently testable.** Kernel can be exercised with deterministic
  fake models and tools—no network required.

## Installation

```bash
# Core framework
pip install kora-agent

# Optional extras
pip install kora-agent[openai]       # OpenAI / OpenAI-compatible providers (openai)
pip install kora-agent[anthropic]    # Anthropic Claude provider (anthropic)
pip install kora-agent[network]      # HTTP / web tools (httpx)
pip install kora-agent[all]          # Everything, including dev tooling

# Kora Code Agent (official coding agent)
pip install kora-agent kora-code
pip install kora-agent[code]         # shortcut for the above
```

Kora requires Python 3.12 or newer and has zero required runtime
dependencies beyond the standard library plus `typing-extensions`.

## Quick Start

### 1. Configure environment

```bash
cp .env.example .env
# Edit .env and set at least one provider key, e.g.
# DASHSCOPE_API_KEY=your-api-key

# Or export inline
export DASHSCOPE_API_KEY='your-api-key'
```

### 2. Define tools

The `@tool` decorator derives name, description, and JSON schema from
the function signature and docstring:

```python
from kora import tool

@tool
def echo(message: str) -> str:
    """Echo back a message."""
    return f"Echo: {message}"

@tool
def calculate(expression: str) -> str:
    """Evaluate a math expression."""
    return str(eval(expression, {"__builtins__": {}}, {}))
```

### 3. Create an agent

```python
from kora import Agent
from kora.providers import get_provider_registry
from kora.tools import ListFilesTool, ReadFileTool

# Resolve a model from the built-in provider registry
registry = get_provider_registry()
model = registry.get_model("dashscope", "qwen-max")

agent = Agent(
    name="assistant",
    system_prompt="You are a helpful assistant.",
    tools=[
        echo,
        calculate,
        ListFilesTool("."),    # filesystem tools are workspace-scoped
        ReadFileTool("."),
    ],
    model=model,
)
```

See [Model Providers](#model-providers) below for all built-in providers
and how to register custom ones.

### 4. Run a session

```python
import asyncio

async def main():
    session = agent.open_session()                       # persists history
    result = await session.send("What files are here?")  # streams events
    print(result)

asyncio.run(main())
```

For a full model-provider implementation and event handling, see
[`examples/demo_quickstart.py`](examples/demo_quickstart.py) and
[`docs/getting-started.md`](docs/getting-started.md).

## Built-in Tools

Kora's toolset follows a capability-based design: a small number of
general tools each cover a family of operations. Use `get_core_tools()`
to get the 6 essential tools for a coding agent.

### File System

| Tool | Description |
|------|-------------|
| `ListFilesTool` | List files/directories (covers `ls`, `find`, `tree`) |
| `SearchTextTool` | Search text in files (covers `grep`/`rg`) |
| `ReadFileTool` | Read file content with line ranges (covers `cat`, `head`, `tail`) |
| `WriteFileTool` | Create or overwrite files |
| `ApplyPatchTool` | Apply targeted text patches to existing files |

### Execution

| Tool | Description |
|------|-------------|
| `RunShellTool` | Execute shell commands with command filtering |
| `PythonExecutionTool` | Execute Python code in a sandboxed environment |

### Network

| Tool | Description |
|------|-------------|
| `HTTPRequestTool` | Make HTTP requests with SSRF protection |
| `WebFetchTool` | Fetch and extract text from web pages |
| `WebSearchTool` | Search the web via DuckDuckGo |

### Convenience helpers

| Helper | Returns |
|--------|---------|
| `get_core_tools(workspace)` | The 6 essential tools for a coding agent |
| `get_filesystem_tools(workspace)` | The 5 filesystem tools |
| `get_execution_tools(workspace)` | `RunShellTool` + `PythonExecutionTool` |
| `get_network_tools()` | The 3 network tools |

## Model Providers

Built-in providers live in `kora.providers` and are resolved through the
provider registry:

| Provider ID | Example models | API key env |
|-------------|----------------|-------------|
| `openai` | `gpt-4o`, `gpt-4-turbo`, `gpt-3.5-turbo` | `OPENAI_API_KEY` |
| `anthropic` | `claude-3-5-sonnet-20241022`, `claude-3-opus-20240229` | `ANTHROPIC_API_KEY` |
| `dashscope` | `qwen-max`, `qwen-plus`, `qwen-turbo` | `DASHSCOPE_API_KEY` |
| `jdcloud` | `glm-5`, `glm-4` | `JDCLOUD_API_KEY` |
| `deepseek` | `deepseek-chat`, `deepseek-reasoner`, `deepseek-v4-flash` | `DEEPSEEK_API_KEY` |
| `deepseek-anthropic` | `deepseek-v4-flash`, `deepseek-v4-pro` (via Anthropic API) | `DEEPSEEK_API_KEY` |
| `moonshot` | `moonshot-v1-8k`, `moonshot-v1-32k`, `moonshot-v1-128k` | `MOONSHOT_API_KEY` |
| `openrouter` | `anthropic/claude-3.5-sonnet`, `openai/gpt-4o` | `OPENROUTER_API_KEY` |
| `ollama` | `llama3`, `mistral`, `qwen2` | local (no key) |

To register a custom provider, add a `ProviderSpec` to the registry:

```python
from kora.providers import ProviderSpec, ModelSpec, get_provider_registry

registry = get_provider_registry()
registry.register(ProviderSpec(
    id="my-provider",
    name="My Provider",
    base_url="https://api.example.com/v1",
    api="openai-completions",       # or "anthropic-messages"
    api_key="${MY_API_KEY}",
    models=(
        ModelSpec(id="my-model", name="My Model", tool_calling=True),
    ),
))
model = registry.get_model("my-provider", "my-model")
```

Provider API keys are read from environment variables (via the
`${VAR_NAME}` pattern in each `ProviderSpec`). See
[`.env.example`](.env.example) for the full list.

## Architecture

Kora separates mechanism from policy across three conceptual layers.
Dependencies always point inward:

```
Interface → Host → Runtime → Kernel
```

| Layer | Responsibility | Style |
|-------|---------------|------|
| **Kernel** | Executes one model-tool loop | Synchronous, dependency-injected, fully testable with fakes |
| **Runtime** | Manages `Agent`, `Session`, `Run`, events | Async, observable, coordinates the Kernel |
| **Host** | Persistence, identity, tenancy, permissions | Pluggable, framework-defined boundary |

The Kernel knows nothing about agents, workspaces, sessions, users, or
databases. The Runtime knows nothing about authentication, tenancy, or
UI rendering. This keeps the core small and replaceable.

See [`docs/decisions/`](docs/decisions/) for the reasoning behind each
architectural boundary, and [`CLAUDE.md`](CLAUDE.md) for the
non-negotiable development constitution.

## Examples

The [`examples/`](examples/) directory contains runnable demos:

| File | Demonstrates |
|------|--------------|
| `demo_quickstart.py` | Basic agent with filesystem tools |
| `demo_runtime.py` | Session lifecycle and event handling |
| `demo_observability.py` | Structured event streams |
| `demo_auto.py` | Auto-mode execution |
| `demo_kernel.py` | Low-level Kernel loop with fakes |
| `demo_real_model.py` | End-to-end run with a live provider |

## Documentation

- [Getting Started](docs/getting-started.md) — Setup and your first agent
- [Tools Guide](docs/tools.md) — All built-in tools and usage patterns
- [API Reference](docs/api.md) — Core public API
- [Current State](docs/CURRENT.md) — What is implemented today
- [Decision Records](docs/decisions/) — Durable architectural decisions

## Development

```bash
# Clone and enter the repo
git clone https://github.com/xvshiting/kora.git
cd kora

# Isolated environment (Python 3.12+)
python3.12 -m venv .venv
source .venv/bin/activate

# Editable install with dev tooling
pip install -e ".[dev]"

# Editable install for kora-code agent (if working on it)
pip install -e ./agents/kora-code

# Verify
pytest            # tests
mypy src/kora     # type check
ruff check src/kora   # lint
```

Before making a substantial change, please read
[`CLAUDE.md`](CLAUDE.md) (project constitution) and
[`docs/CURRENT.md`](docs/CURRENT.md) (current design state).

## Roadmap

Kora is currently **Alpha**. Active and planned work, summarized from
[`TODO.md`](TODO.md):

- **Host layer** — pluggable persistence, identity, and permissions
  (a basic `load_agent_from_markdown` loader exists; full persistence
  and tenancy are still pending).
- **Advanced features** — multi-agent collaboration, tool chaining,
  memory/context management, streaming output.
- **CLI & deployment** — `kora` CLI, server mode, Docker support.
- **Provider hardening** — the provider-centric architecture is in place,
  including multiple built-in providers, error handling, retries, and
  streaming primitives; it still needs compatibility verification and
  expanded integration coverage.

## Contributing

Kora is intentionally small. When proposing changes:

1. Identify which architectural layer owns the change.
2. Prefer the smallest complete change; add tests with behavior changes.
3. Do not cross established layer boundaries or move framework
   responsibilities into user code.
4. Update `TODO.md` and `docs/CURRENT.md` after substantial work, and
   record durable decisions under `docs/decisions/` when necessary.

See [`CLAUDE.md`](CLAUDE.md) for the full development constitution.

## License

MIT — see `license` field in [`pyproject.toml`](pyproject.toml).
