Metadata-Version: 2.4
Name: hajimi
Version: 0.1.0
Summary: Async-first Python agent framework with tools, skills, MCP, sessions, and tracing.
Requires-Python: >=3.14
Requires-Dist: any-llm-sdk[anthropic,gemini,openai]>=1.14.0
Requires-Dist: anyio>=4.13.0
Requires-Dist: click>=8.3.3
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic>=2.11.0
Requires-Dist: sqlalchemy>=2.0.44
Provides-Extra: mcp
Requires-Dist: mcp>=1.12.4; extra == 'mcp'
Provides-Extra: observability
Requires-Dist: opentelemetry-api>=1.39.0; extra == 'observability'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.39.0; extra == 'observability'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.39.0; extra == 'observability'
Requires-Dist: opentelemetry-sdk>=1.39.0; extra == 'observability'
Provides-Extra: sandbox-e2b
Requires-Dist: e2b>=2.3.0; extra == 'sandbox-e2b'
Description-Content-Type: text/markdown

# Hajimi Agent

Hajimi is a small async-first Python agent framework built around
`any-llm-sdk` direct async APIs.

Core capabilities:

- TOML and `.env` based configuration.
- Loguru console and rotating file logging.
- Async completion, streaming completion, embedding, and Responses API wrappers.
- A typed corekit with message parts, stream events, context objects, and a
  compact agent loop with optional tool dispatch.
- Workspace read/search tools, opt-in write/shell tools, local skills with
  progressive activation, optional MCP tools, BM25 tool search, agent-as-tool
  subagents, and persistent in-process teammates.
- Durable `AgentSession` context with JSONL events, SQLAlchemy ORM indexes
  defaulting to SQLite, forks, edit/delete/restore markers, compaction, and
  token reports with optional provider cache usage.
- JSONL tracing with optional OpenTelemetry export.
- Pytest coverage for configuration, logging, LLM wrappers, tools, skills, MCP,
  sessions, tracing, subagents, teammates, workspace tools, and dynamic tool
  search.

Quick start:

```bash
uv sync
cp examples/configs/.env.example examples/configs/.env
uv run python examples/basic_agent.py
uv run pytest -q
```

Examples:

```bash
uv run python examples/basic_agent.py
uv run python examples/stream.py
uv run python examples/tools.py
uv run python examples/custom_loop.py
uv run python examples/session.py
uv run python examples/routed_runtime.py
uv sync --extra mcp
uv run python examples/mcp_stdio.py
```

Minimal one-call usage (no TOML required):

```python
# Export at least one provider key, e.g.:
#   export OPENAI_API_KEY=...        # auto-detected as the openai default
#   export DEEPSEEK_API_KEY=...      # auto-detected as the deepseek default
#   export HAJIMI_DEFAULT_MODEL=openai   # optional, when several keys are set
from hajimi import Hajimi
print(await Hajimi.ask("hello"))
```

Typed core API:

```python
from hajimi import TextDelta, user_message

async with agent.run_stream([user_message("hello")]) as run:
    async for event in run:
        if isinstance(event, TextDelta):
            print(event.chunk, end="")

print(run.output)
```

Custom loop API:

```python
from collections.abc import AsyncIterator

import hajimi as ai


class CustomAgent(ai.Agent):
    async def loop(self, context: ai.Context) -> AsyncIterator[ai.AgentEvent]:
        while context.keep_running():
            async with (
                ai.stream(context=context) as stream,
                ai.ToolRunner() as tools,
            ):
                async for event in ai.merge(stream, tools.events()):
                    yield event
                    if isinstance(event, ai.ToolEnd):
                        tools.schedule(context.resolve(event.tool_call))

                context.add(stream.message)
                context.add(tools.get_tool_message())
```

Power-user knobs travel on a single `RunOptions` object:

```python
from hajimi import AgentRuntime, RunOptions, load_config

runtime = await AgentRuntime.from_config(await load_config())
result = await runtime.run_task(
    "draft a release note for v0.2",
    options=RunOptions(
        mode="auto",
        max_cost_usd=0.05,
        max_total_tokens=8000,
        on_budget_exceeded="stop",
    ),
)
print(result.content, result.cost)
```

Optional extras:

```bash
uv sync --extra mcp
uv sync --extra observability
```

Docs:

- [Configuration](docs/configuration.md)
- [Observability](docs/observability.md)
- [Context](docs/context/index.md)
- [Skills](docs/skills.md)
- [MCP](docs/mcp.md)
- [Multi-agent](docs/multi-agent.md)
- [Research notes](docs/research.md)
