{"id":"361e4b3f-6499-4bf9-9527-29f6f68bec33","slug":"unchain","kind":"mcp","name":"unchain","summary":"A lightweight Python agent framework for building tool-using AI runtimes.","owner":"haoxiang-xu","repoUrl":"https://github.com/haoxiang-xu/unchain","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-02-14T02:52:39.000Z","addedAt":"2026-10-21T20:37:08.990Z","logoUrl":"https://avatars.githubusercontent.com/u/59581718?u=ea16085ee376512d732148a91499002d3f38117d&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T21:11:16.537Z","sample":false,"url":"https://conduits.dev/tools/unchain","language":"Python","transports":["stdio"],"install":{"pypi":"unchain"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n  <img src=\"./assets/unchain.png\" alt=\"unchain\" style=\"height: 100px; margin-bottom: 32px;\" />\n  <h1>unchain</h1>\n  <p>A lightweight Python agent framework for building tool-using AI runtimes</p>\n</div>\n\n[![Version](https://img.shields.io/badge/version-0.2.0-2563eb)](pyproject.toml)\n[![Python](https://img.shields.io/badge/python-3.12%2B-3776AB)](pyproject.toml)\n[![License](https://img.shields.io/badge/license-Apache%202.0-0ea5e9)](LICENSE)\n\nDocs: [English](docs/README.en.md) | [中文](docs/README.zh-CN.md)\n\n---\n\n## What is unchain?\n\nunchain is a modular agent framework that separates **agent configuration** from **execution**. It provides a harness-driven kernel loop, pluggable provider support, multi-tier memory, and a rich tool system — all composable through a clean module API.\n\nEverything lives under one package: `src/unchain/`. Agent behaviour is composed by passing modules (`ToolsModule`, `MemoryModule`, `PoliciesModule`, `OptimizersModule`, `SubagentModule`, `ToolDiscoveryModule`) into `Agent`.\n\n## Install\n\n```bash\npip install -e \".[dev]\"\n```\n\n**Prerequisites**: Python 3.12+\n\n`uv sync --locked --all-extras` installs the reviewed dependency versions. The\nlegacy `requirements.txt` retains the notebook environment and can be installed\nalongside `-e \".[dev]\"`.\n\nTo retain Intel macOS and 32-bit Windows support, `cryptography` is temporarily\nheld at `>=48.0.1,<49`. Three advisories remain open pending a compatible upstream\nfix or a separate platform-support decision:\n[GHSA-g6cj-pr64-35w5](https://github.com/advisories/GHSA-g6cj-pr64-35w5),\n[GHSA-jwv3-5hgf-82ww](https://github.com/advisories/GHSA-jwv3-5hgf-82ww), and\n[GHSA-m2h6-j472-rp4c](https://github.com/advisories/GHSA-m2h6-j472-rp4c).\n\n## Quick Start\n\n```python\nfrom unchain import Agent\nfrom unchain.agent import ToolsModule\nfrom unchain.toolkits import CoreToolkit\n\nagent = Agent(\n    name=\"coder\",\n    provider=\"openai\",\n    model=\"gpt-5\",\n    instructions=\"You are a coding assistant.\",\n    modules=(\n        ToolsModule(tools=(CoreToolkit(workspace_root=\".\"),)),\n    ),\n)\n\nresult = agent.run(\"Inspect the repo and explain what matters.\")\nprint(result.messages[-1][\"content\"])\n```\n\n### Custom Tools\n\n```python\nfrom unchain import Agent\nfrom unchain.agent import ToolsModule\nfrom unchain.tools import tool\n\n@tool\ndef fetch_price(ticker: str) -> dict:\n    \"\"\"Fetch the latest stock price for a given ticker symbol.\"\"\"\n    return {\"ticker\": ticker, \"price\": 142.50}\n\nagent = Agent(\n    name=\"analyst\",\n    provider=\"anthropic\",\n    model=\"claude-sonnet-4\",\n    modules=(ToolsModule(tools=(fetch_price,)),),\n)\n```\n\n### Subagents (multi-agent work)\n\n`Team` is no longer a top-level primitive. Compose multi-agent flows by giving a planner agent a `SubagentModule` so it can spawn typed children:\n\n```python\nfrom unchain import Agent\nfrom unchain.agent import SubagentModule\nfrom unchain.subagents import SubagentPolicy, SubagentTemplate\n\nplanner = Agent(\n    name=\"planner\",\n    provider=\"openai\",\n    model=\"gpt-5\",\n    instructions=\"Plan the work, then delegate.\",\n    modules=(\n        SubagentModule(\n            templates=(\n                SubagentTemplate(name=\"researcher\", instructions=\"Research the question.\"),\n                SubagentTemplate(name=\"writer\", instructions=\"Write a report from the research.\"),\n            ),\n            policy=SubagentPolicy(max_depth=4, max_total_agents=8),\n        ),\n    ),\n)\n\nresult = planner.run(\"Write a report on recent AI trends.\")\n```\n\nThe planner gets `delegate_to_subagent`, `handoff_to_subagent`, and `spawn_worker_batch` tools; see [docs/en/skills/agent-and-team.md](docs/en/skills/agent-and-team.md) for the full surface.\n\n## Architecture\n\n```\nAgent.run(messages)\n  |\n  v\nAgentBuilder --> PreparedAgent --> KernelLoop.run()\n                                      |\n                    +------ step_once() loop ------+\n                    |                              |\n                    v                              v\n            dispatch_phase()              fetch_model_turn()\n            (harnesses run)               (provider SDK call)\n                    |                              |\n                    v                              v\n          Memory / Optimizers             Tool Execution\n          Context Injection               Confirmation Gates\n                    |                     Human Input Suspend\n                    v\n             HarnessDelta applied to RunState\n                    |\n                    v\n              KernelRunResult\n```\n\n### Kernel Phases\n\nHarnesses plug into these runtime phases:\n\n| Phase | When | Example |\n|-------|------|---------|\n| `bootstrap` | Run initialization | Load memory |\n| `before_model` | Before each LLM call | Inject context, optimize window |\n| `after_model` | After LLM response | Process response |\n| `on_tool_call` | Per tool invocation | Confirmation gates |\n| `after_tool_batch` | All tools in batch done | Commit observations |\n| `before_commit` | Before memory persist | Finalize state |\n| `on_suspend` / `on_resume` | Pause/resume | Human input flow |\n\n### Delta-Based State\n\nAll state mutations flow through immutable `HarnessDelta` objects:\n\n```python\nHarnessDelta.append(\n    created_by=\"my_harness\",\n    messages=[{\"role\": \"assistant\", \"content\": \"...\"}],\n    state_updates={\"my_key\": value},\n)\n```\n\n## Providers\n\n| Provider | Models | Streaming | Tools | Reasoning |\n|----------|--------|-----------|-------|-----------|\n| OpenAI | gpt-5, gpt-4.1, gpt-5-codex | Yes | Yes | Yes (gpt-5) |\n| Anthropic | claude-sonnet-4, claude-opus-4-6, claude-haiku-3.5 | Yes | Yes | Yes (thinking) |\n| Google Gemini | gemini-3.8-flash, gemini-3.6-flash, gemini-3.5-flash, gemini-3.1-pro-preview | Yes | Yes | Yes (thinking levels) |\n| Ollama | Any local model | Yes | Yes | Model-dependent |\n| SAP Hyperspace | hyperspace--claude-opus-4-6/4-7, hyperspace--claude-sonnet-4-6, hyperspace--claude-haiku-4-5 | Yes | Yes | Yes (thinking) |\n\nConfigure via environment variables:\n\n```bash\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\nGEMINI_API_KEY=...\n```\n\n## Built-in Toolkits\n\n| Toolkit | Description |\n|---------|-------------|\n| **CoreToolkit** | File read/write, directory listing, text search, line editing, shell execution, LSP, web fetch, structured user questions |\n| **PlanToolkit** | Workspace-backed structured planning with draft, update, read, list, and finalize tools |\n| **AgentReachToolkit** | Read-only Agent Reach helpers for status checks, web pages, and YouTube metadata |\n| **MCPToolkit** | Bridge MCP (Model Context Protocol) servers as native toolkits |\n\nToolkits are also discoverable from local directories and entry-point plugins.\n\n## Skills\n\nDrop a `SKILL.md` (or flat `<name>.md`) file into `.unchain/skills/<name>/` or `.agents/skills/<name>/`, add `SkillsModule()` to the agent's modules, and it's discovered automatically — no registration code needed. `SkillsModule` renders a name+description catalog, exposes a `skill` tool the model can call to activate one by name, and lets the user activate one directly with `/name` in their own message. Activations are projected into a durable `<active_skills>` system block that survives compaction, resume, and cold restart.\n\nSee [Agent Skills](docs/en/skills/agent-skills.md) for the full frontmatter contract, discovery roots, and wire format.\n\n## Memory System\n\nTwo-tier memory with pluggable backends:\n\n```python\nfrom unchain.memory import MemoryConfig, MemoryManager\n\nconfig = MemoryConfig(\n    last_n_turns=8,\n    vector_top_k=4,\n    long_term_enabled=True,\n)\n```\n\n| Tier | Storage | Purpose |\n|------|---------|---------|\n| **Short-term** | In-memory / JSON sessions | Recent conversation context |\n| **Long-term** | Qdrant vector DB | Semantic recall, fact extraction, profiles |\n\nStrategies: `LastNTurns`, `SummaryToken`, `Hybrid`\n\n## Modules\n\nAgents are composed through pluggable modules:\n\n```python\nfrom unchain.agent import Agent, ToolsModule, MemoryModule, PoliciesModule\nfrom unchain.toolkits import CoreToolkit\n\ncore_toolkit = CoreToolkit(workspace_root=\".\")\n\nagent = Agent(\n    name=\"assistant\",\n    provider=\"openai\",\n    model=\"gpt-5\",\n    modules=(\n        ToolsModule(tools=(core_toolkit,)),\n        MemoryModule(memory=memory_manager),\n        PoliciesModule(max_iterations=32),\n    ),\n)\n```\n\n| Module | Purpose |\n|--------|---------|\n| `ToolsModule` | Register tools and toolkits |\n| `MemoryModule` | Attach memory manager |\n| `PoliciesModule` | Set iteration limits, subagent policies |\n| `OptimizersModule` | Context window optimizers |\n| `SubagentModule` | Register subagent templates |\n\n## Subagents\n\nAgents can delegate, handoff, or spawn parallel workers:\n\n```python\nfrom unchain.agent import SubagentModule\nfrom unchain.subagents import SubagentTemplate\n\ntemplates = [\n    SubagentTemplate(name=\"researcher\", agent=research_agent, allowed_modes=(\"delegate\",)),\n    SubagentTemplate(name=\"coder\", agent=code_agent, allowed_modes=(\"worker\",), parallel_safe=True),\n]\n\nparent = Agent(\n    name=\"coordinator\",\n    modules=(SubagentModule(templates=templates),),\n    ...\n)\n```\n\n## Context Optimizers\n\nPluggable strategies for managing the context window:\n\n| Optimizer | Strategy |\n|-----------|----------|\n| `LastNOptimizer` | Keep last N messages |\n| `LlmSummaryOptimizer` | Summarize older messages with LLM |\n| `ToolHistoryCompactionOptimizer` | Compress verbose tool results |\n| `PinnedContextOptimizer` | Preserve pinned file context |\n| `SlidingWindowOptimizer` | Token-aware context window truncation |\n\n## Package Layout\n\n```\nsrc/\n  unchain/\n    __init__.py               # Public API: Agent\n    agent/                    # Agent, AgentBuilder, PreparedAgent, modules\n    kernel/                   # KernelLoop, RuntimeHarness, RuntimePhase, types\n    providers/                # OpenAI, Anthropic, Ollama ModelIO\n    tools/                    # Tool, Toolkit, registry, catalog, discovery, execution\n    toolkits/                 # CoreToolkit, PlanToolkit, AgentReachToolkit, MCPToolkit\n    memory/                   # MemoryManager, KernelMemoryRuntime, harnesses\n    optimizers/               # Context window / token compaction harnesses\n    subagents/                # Subagent executor + delegation tools\n    retry/                    # Provider-agnostic retry layer\n    schemas/                  # ResponseFormat (structured output)\n    input/                    # Human input + media\n    character/                # Persona / instruction helpers\n    runtime/                  # Legacy Broth runtime kept only for LegacyBrothModelIO\n    types/                    # Shared type aliases\ntests/\n  evals/                      # Scenario-based evaluation framework\ndocs/\n  en/                         # English docs (skills chapters + API reference)\n  zh-CN/                      # Chinese docs\n```\n\n## Public API\n\n```python\n# Top-level\nfrom unchain import Agent\n\n# Agent + modules\nfrom unchain.agent import (\n    AgentBuilder, PreparedAgent,\n    ToolsModule, MemoryModule, PoliciesModule,\n    OptimizersModule, SubagentModule, ToolDiscoveryModule,\n)\n\n# Kernel\nfrom unchain.kernel import KernelLoop, KernelRunResult, RunState, RuntimeHarness, RuntimePhase\n\n# Tools\nfrom unchain.tools import (\n    Tool, Toolkit, tool, ToolParameter, ToolkitRegistry,\n    ToolkitCatalogRuntime, ToolkitCatalogConfig,\n    ToolDiscoveryRuntime, ToolDiscoveryConfig,\n)\n\n# Providers\nfrom unchain.providers import OpenAIModelIO, AnthropicModelIO, OllamaModelIO\n\n# Toolkits\nfrom unchain.toolkits import AgentReachToolkit, CoreToolkit, MCPToolkit, PlanToolkit\n\n# Memory\nfrom unchain.memory import MemoryConfig, MemoryManager, KernelMemoryRuntime\n\n# Subagents\nfrom unchain.subagents import SubagentPolicy, SubagentTemplate, SubagentExecutor\n\n# Schemas\nfrom unchain.schemas import ResponseFormat\n```\n\n## Testing\n\n```bash\n# Setup\n./scripts/init_python312_venv.sh\n\n# Run tests\n./run_tests.sh\n\n# Or directly\nPYTHONPATH=src pytest tests/ -q\n```\n\n## Documentation\n\nFull bilingual docs with skills chapters and API reference:\n\n**Skills Chapters**: Architecture Overview, Agent & Subagents, Runtime Engine, Tool System Patterns, Memory System, Creating Toolkits, Testing Conventions\n\n**API Reference**: Agents, Runtime, Interaction, Durable Jobs, Tools, Toolkits, Memory, Input/Workspace/Schemas\n\n**Appendices**: Class Index (55+ classes), Export Index, Glossary, Return Shapes\n\nSee [docs/README.en.md](docs/README.en.md) for the full reading guide.\n\n## License\n\n[Apache 2.0](LICENSE)\n"}