Skip to main content

linch

An embeddable agent harness for context-heavy Python applications.

linch is an async-first, event-driven Python SDK for building agent loops inside your own application.

Linch 2.0 is intentionally an SDK rather than a coding-agent product: a bare Agent is domain-neutral and has no implicit workspace or shell authority. Choose a tool registry or preset explicitly. Upgrading from 1.x? Read the 2.0 migration guide.

It gives you the runtime pieces that production agents usually need but simple tool-calling wrappers leave to you: streamed events, tool scheduling, context/RAG, tiered memory, virtual filesystem offloading, structured outputs, permissions, retries, provider adapters, cost tracking, evals, MCP, skills, and subagents.

Use linch when you want to build your own domain workflow — not force it into a hosted assistant, a rigid graph DSL, or a black-box multi-agent abstraction.


Why linch?

Most agent frameworks start from one of three ideas:

  • agents as chat loops — simple, but hard to control once tools, context, memory, and side effects grow;
  • agents as graphs — explicit and durable, but sometimes too heavy for application-level workflows;
  • agents as teams — useful for collaboration patterns, but not always the right abstraction for context-heavy product features.

linch starts from a different idea:

An agent is a runtime you embed, observe, constrain, and feed with the right context.

That means linch focuses on the boring-but-critical layer between your app and the model:

  1. Context control — build RAG/context per turn before the model sees it.
  2. Tool control — schedule tools with resource awareness, timeout, retry, and permission checks.
  3. State control — keep sessions, memory, files, citations, and large outputs manageable.
  4. Provider control — run against different model providers without rewriting your workflow.

What you can build

linch is designed for application developers building agentic features such as:

  • document and report assistants;
  • RAG systems over large internal knowledge bases;
  • coding and software-engineering agents;
  • extraction and synthesis workflows;
  • long-running research assistants;
  • local/offline agent demos;
  • tools that need citations, permissions, filesystem state, or large-result offloading.

Core features

Area What linch provides
Agent loop Agent, Session, async event streaming, loop guards
Tools Duck-typed tools, runtime registries, parallel scheduling, resource locks, local or Docker-backed Bash execution
Reliability Per-tool timeout, opt-in retry, structured tool errors, recovery hints
Context ContextBuilder, RAG context injection, context budgets, compaction ladder (micro-compact, reactive recovery, circuit breaker)
Memory Search/upsert tools, flat and tiered memory stores, persistent memory examples
Filesystem Virtual filesystem, automatic large-result offloading, disk/state/sqlite backends
Safety Permission engine, tool/path/bash rules, dangerous-action skipping
Budgets RunBudget token/USD caps shared across the subagent tree, warning + exceeded events, graceful stop
Workflows Deterministic fleet loops: wf.agent/parallel/pipeline/phase, journaled resume, shared budgets
Providers OpenAI Responses, OpenAI Chat Completions, Anthropic, Gemini, llama.cpp, OpenAI-compatible endpoints, pluggable providers
Extensibility Python hooks, MCP, skills, subagents (fork/continue, background workers, coordinator mode), observer compatibility
Outputs Structured output schemas, citations, usage/cost events, metadata-rich tool results, run reports

Architecture

flowchart LR
    App[Your application] --> Session[Session]
    Session --> Loop[Agent loop]

    Loop --> Provider[Model provider]
    Loop --> Scheduler[Tool scheduler]
    Loop --> Context[Context builder]
    Loop --> Memory[Memory]
    Loop --> FS[Virtual filesystem]
    Loop --> Permissions[Permission engine]

    Context --> RAG[RAG / retrieval]
    Scheduler --> Tools[Tools]
    Tools --> FS
    Tools --> Citations[Citations & metadata]

    Loop --> Events[Streaming events]
    Events --> UI[CLI / Web UI / API]

linch keeps the loop small, but makes the surrounding runtime explicit: context, tools, permissions, state, files, memory, and events are all first-class parts of the system.


Install

From PyPI:

pip install linch

With optional extras (Anthropic, MCP, Gemini, OpenTelemetry, Postgres):

pip install 'linch[anthropic,mcp,gemini]'

For local development:

pip install -e '.[dev,mcp,anthropic,gemini]'

Quickstart

New to Linch? The step-by-step guide is in docs/usage/quickstart.md, including an offline smoke test that runs without an API key.

import asyncio
import os

from linch import Agent, InMemorySessionStore

agent = Agent(
    model="gpt-5",
    openai_api_key=os.environ.get("OPENAI_API_KEY"),
    session_store=InMemorySessionStore(),
    permissions={"mode": "skip-dangerous"},
)

async def main():
    session = await agent.session()

    async for event in session.run("Explain what an embeddable agent SDK is in one paragraph."):
        if event.type == "result":
            print(event.final_text)

asyncio.run(main())

For a coding/workspace agent, make that authority visible at construction:

from linch import Agent, workspace_tools

agent = Agent(model="gpt-5", tools=workspace_tools())

Put OPENAI_API_KEY=... in .env or export it in your shell. Never commit .env.


Safe local demos

These examples exercise useful local code paths without requiring a live provider call.

python3 examples/tools/parallel_search_agent.py
python3 examples/tools/runtime_tools.py
python3 examples/context/rag_context_builder.py
python3 examples/memory/memory_agent.py
python3 examples/tools/tool_reliability_agent.py
python3 examples/memory/sqlite_memory_agent.py

# Filesystem offload — fully offline, no API key needed
python3 examples/tools/filesystem_offload.py

Core concepts

Agent and Session

An Agent owns shared configuration: model, provider, tools, permissions, hooks, memory, and session store.

A Session represents one conversation or workflow run. One agent can serve many sessions.

Deep agent preset

create_deep_agent() returns an Agent with long-horizon orchestration defaults: durable run/session SQLite storage, task planning tools, specialist subagents (researcher, planner, implementer), a persistent /memories virtual filesystem partition, and deepened system prompt with planning/verification doctrine.

coordinator=True turns the parent into a pure orchestrator — it loses heavy tools (Edit/Write/Bash) and gains SubagentContinueTool and TaskStopTool. Workers receive full tool access. Background workers (run_in_background=True on Subagent) deliver results via <task-notification> at the top of the next turn. Fork/continue lets you re-engage any retained worker with its full prior context via SubagentContinue.

Background delivery is in-process: a RunStore keeps status audit telemetry, but active detached tasks and result notifications are not reconstructed after a process restart. Use an application-owned durable queue/workflow when that delivery guarantee is required.

Events

linch streams the loop as events instead of hiding execution behind a blocking function call. This makes it easier to build CLIs, web UIs, background workers, and observability integrations.

Hooks

Hooks are the canonical extension mechanism for the agent loop. Register Python hook objects with Agent(hooks=[...]) to inspect or control the run at typed chokepoints: agent start/stop, prompt submit, turn start/stop, provider calls, pre/post tool use, final answer, stop, subagent start/stop, and event emission.

Built-in adapters are available when you want a standard extension as a hook: ContextInjectionHook, ToolMiddlewareHook, RunTelemetryHook, FinalAnswerVerifierHook, and StopPredicateHook.

from linch import Agent, HookResult, workspace_tools

class GuardTools:
    def on_pre_tool_use(self, ctx):
        if ctx.tool_name == "Bash" and "rm -rf" in str(ctx.input.get("command", "")):
            return HookResult.block("blocked dangerous command")
        return None

agent = Agent(
    model="gpt-5",
    tools=workspace_tools(),
    hooks=[GuardTools()],
    permissions={"mode": "skip-dangerous"},
)

Tools and scheduler

Tools are duck-typed Python objects. They can declare schemas, scopes, resources, timeouts, summaries, and execution behavior. The scheduler runs compatible tool calls in parallel while respecting resource constraints and permission rules.

For simple tools, use @tool; it creates the same Tool-compatible object that the registry and scheduler already understand:

from linch import Agent, InMemorySessionStore, ToolContext, empty_tools, tool

@tool(description="Look up an internal document.")
async def search_docs(query: str, ctx: ToolContext) -> str:
    return await ctx.deps.search(query)

agent = Agent(
    model="gpt-5",
    tools=empty_tools(search_docs),
    deps=my_vector_store,
    session_store=InMemorySessionStore(),
)

ContextBuilder

ContextBuilder lets you construct turn-specific context before the model runs. It is implemented as a built-in hook adapter; for new cross-cutting extension work, prefer Agent(hooks=[...]).

Memory

linch includes memory primitives and tools for searching and upserting reusable facts. Memory can be in-memory, sqlite-backed, tiered by working/episodic/semantic buckets, or replaced with your own store.

Virtual filesystem

Large tool results should not always stay in the model context. linch can offload large outputs to a virtual filesystem and pass references back into the loop.

Permissions

The permission engine controls dangerous actions at the runtime layer. You can define tool, path, and bash rules instead of relying only on prompts.

Providers

linch separates the agent runtime from the model provider. Built-in providers include OpenAI Responses, OpenAI Chat Completions, DeepSeek, Anthropic, Gemini, and llama.cpp. Use DeepSeekProvider for the native DeepSeek API, or OpenAI Chat Completions with base_url for generic compatible endpoints, and inspect known direct-provider models with list_provider_models().


When to use linch

linch is a good fit when you need:

  • an agent loop embedded inside your own Python application;
  • streaming events for UI, API, or worker integration;
  • explicit control over tools, permissions, retries, and timeouts;
  • RAG/context construction as a first-class runtime step;
  • memory and filesystem state across longer workflows;
  • provider flexibility without rewriting application logic;
  • a small runtime layer you can build domain-specific workflows on top of.

When not to use linch

linch may be more than you need if:

  • your feature is a single stateless LLM call;
  • you want a no-code agent builder;
  • you want a fully hosted assistant platform;
  • you want every workflow expressed as a static graph from day one;
  • you only need a thin wrapper around one provider's API.

Examples

Examples are organized by subsystem under examples/.

examples/core/ — agent fundamentals and real-world patterns

File What it shows
core/tiny_agent.py Smallest possible agent
core/coding_agent.py SWE agent — full tool set, BashRule/PathRule safety fence, LoopGuard, multi-turn
core/policy_aware_execution.py Docker-backed Bash execution — permission rules plus opt-in runtime restrictions
core/reading_agent.py Read-only codebase Q&A — no write/edit/bash, custom reviewer persona
core/chat_agent.py Pure conversation agent — no tools, custom domain, structured output, ContextBuilder injection
core/custom_permissions.py All permission modes and rule types
core/system_prompts.py append, replace, per-session override, persona patterns
core/structured_output.py OutputSchema, final_tool_name, JSON extraction
core/event_streaming.py Consuming events for SSE, WebSocket, CLI progress
core/multi_session.py One Agent, many users, shared deps
core/deep_agent_resume.py create_deep_agent() — 4 demos: planning + /memories + run resume; background worker + notification; fork/continue retained worker; coordinator orchestration
core/loop_guard_agent.py LoopGuard — identical-call and failure-streak detection
core/budget_capped_agent.py RunBudget — token cap, 90% warning event, graceful exceeded stop
core/compaction_ladder_agent.py CompactionLadder — micro-compact rung, reactive recovery, circuit breaker
core/workflow_fleet.py agent.run_workflow() — parallel fan-out, pipeline, shared budget, crash + journal resume
core/interactive_cli.py Interactive REPL

examples/tools/ — tool patterns and scheduler

File What it shows
tools/custom_tools.py 5 tool patterns: read, write, exec, parallel, with deps
tools/parallel_search_agent.py Scheduler V2: parallel search, resources, concurrency cap
tools/runtime_tools.py Runtime registry add/remove/replace/select and schema export
tools/tool_reliability_agent.py Timeout, per-tool opt-out, RetryOptions
tools/filesystem_offload.py Virtual filesystem backends, auto-offload of large results (offline)

examples/context/ — RAG and context hooks

File What it shows
context/context_injection.py ContextInjectionHook patterns: RAG per-turn, budget, selected tools
context/rag_context_builder.py ContextInjectionHook RAG with metadata and budget reporting

examples/memory/ — memory primitives

File What it shows
memory/memory_agent.py Core memory primitives with search/upsert tools and citations
memory/sqlite_memory_agent.py SqliteMemoryStore — persistent memory, round-trip, upsert update
memory/pgvector_memory.py Postgres memory example with optional vector-style retrieval

examples/observability/ — telemetry hooks and tracing

File What it shows
observability/observability_agent.py RunTelemetryHook with LoggingObserver + optional OpenTelemetryObserver
observability/custom_observer.py Custom observer: latency tracking, error counts per tool

examples/providers/ — provider-specific features

File What it shows
providers/openai_agent.py OpenAI Chat Completions — basic, thinking, tool use, structured output, multi-turn
providers/anthropic_agent.py Anthropic — extended thinking, prompt caching, tool-backed structured output
providers/deepseek_agent.py DeepSeek via OpenAI-compatible and Anthropic-compatible endpoints

examples/integrations/ — subagents, skills, MCP

File What it shows
integrations/subagent_coordinator.py Agent definition files, tool-filtered subagents, SubagentEvent
integrations/multi_agent_isolation.py Context isolation, sequential pipeline, parallel analysts, subagent + filesystem offload (offline)

Public API

The supported, semver-governed API is exactly linch.__all__. Import supported names from the top-level package:

from linch import (
    Agent,
    BashRule,
    EvalCase,
    PathRule,
    ScriptedProvider,
    ToolRule,
    run_eval,
)

This surface includes the core agent/session runtime, provider adapters, typed events, tools and extension contracts, workflow/deep-agent/loop primitives, permission rules, and the complete deterministic eval harness and built-in scorers. Submodule paths are implementation details rather than compatibility promises. See docs/versioning.md for the contract and pinning policy.


Documentation

File What it covers
docs/usage/ Getting started, install, config, providers, tools, hooks, structured output, RAG, workflows, deep agent
docs/architecture.md Internal data flow, module contracts, design invariants
docs/contributing.md Dev setup, code rules, test conventions, PR checklist
examples/ Runnable examples by subsystem

Development

pytest
ruff check . && ruff format --check .
pyright

See docs/contributing.md for the full contributor guide.


Name

linch blends two ideas:

靈 linh In classical Sino-Vietnamese, 靈 carries the meaning of spirit, effortless intelligence, and vital agility — an unseen force that makes a mechanism feel alive.
cinch A saddle harness piece; English slang for easy, simple, sure.

A linch is small — a single pin — but it holds the wheel on the axle. That is the SDK's ambition: the smallest harness that makes complex agent orchestration feel like a cinch.

靈活簡便,以一馭萬。
Linh hoạt giản tiện, dĩ nhất ngự vạn.
"Agile and simple — govern ten thousand things with one."

Metadata

Release files for linch 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for linch 2.0.0
File Size Uploaded Provenance Actions
linch-2.0.0.tar.gz 1.0 MB Without provenance Details for linch-2.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for linch 2.0.0
File Interpreter ABI Platform Actions
linch-2.0.0-py3-none-any.whl Python 3 none any Details for linch-2.0.0-py3-none-any.whl

Total release size: 1.5 MB

Release files / linch-2.0.0.tar.gz

Download URL linch-2.0.0.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
14f402b56413bdbc6910a1b760ae9bcb16a25072e8503c19b75b5840f685408a
BLAKE2b-256 checksum
How to use checksums
cde62712537731402275d4eea1fb466691ef4cbcfe6ca06b0394098f2c95ebb0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14

Release files / linch-2.0.0-py3-none-any.whl

Download URL linch-2.0.0-py3-none-any.whl
Size 458.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
543af3ef40dcb385b3f0c970bd675049c41d313e90b79192370f2793b103c1ff
BLAKE2b-256 checksum
How to use checksums
c5a8613ae62505c03326bf6e9d57086af9a95f7b1fc9fb07add2304da971506b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14

Security for linch 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page