Skip to main content
╔════════════════════════════════════════════════════════════════════════════════════╗
║                                                                                    ║
║    █████╗  ██████╗ ███████╗███╗   ██╗████████╗██╗      █████╗ ███╗   ██╗███████╗   ║
║   ██╔══██╗██╔════╝ ██╔════╝████╗  ██║╚══██╔══╝██║     ██╔══██╗████╗  ██║██╔════╝   ║
║   ███████║██║  ███╗█████╗  ██╔██╗ ██║   ██║   ██║     ███████║██╔██╗ ██║█████╗     ║
║   ██╔══██║██║   ██║██╔══╝  ██║╚██╗██║   ██║   ██║     ██╔══██║██║╚██╗██║██╔══╝     ║
║   ██║  ██║╚██████╔╝███████╗██║ ╚████║   ██║   ███████╗██║  ██║██║ ╚████║███████╗   ║
║   ╚═╝  ╚═╝ ╚═════╝ ╚══════╝╚═╝  ╚═══╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝   ║
║                                                                                    ║
║                the open runtime for persistent, addressable agents                 ║
║                                                                                    ║
║          identity • inbox • state • delivery • local → distributed                 ║
║                                                                                    ║
╚════════════════════════════════════════════════════════════════════════════════════╝

AgentLane gives an AI agent a stable address, an inbox, and state that lasts longer than a single run. You can swap the model, the harness, the process, or the machine underneath it, and the agent is still the same agent.

The idea comes from a simple observation: a single agent loop stops scaling once you need background jobs, long-running work, human review, specialist agents, and plain deterministic services working together. Those are not prompt problems. They are distributed systems problems, and the fix is to treat agents like members of an organization, each with an identity, an inbox, and state of its own. The full argument is in Distributed Agents Are What Make AI Systems Work Like Organizations.

PyPI Python 3.12 npm License: MIT

See it · Why · Install · Quick start · Other harnesses · Layers · Docs · Examples · Changelog

See it

Two processes, two models, one agent. The agent keeps its address and its memory in a file. Everything else changes underneath it.

care_navigator.md:

---
name: care-navigator
description: Follows a patient's medication questions over time.
---
You are a concise patient care navigation agent. Remember what you were told
about a patient and give one clear next step.

monday.py:

import asyncio
import os

from agentlane_openai import ResponsesClient

from agentlane.harness.agents import DefaultAgent
from agentlane.models import Config


async def main() -> None:
    agent = DefaultAgent.from_markdown(
        "care_navigator.md",
        model=<model_client_openai>,
        state_path=".agentlane/care-navigator.json",
    )
    await agent.run("Patient 4471 started lisinopril today. Keep an eye on it.")
    print(agent.agent_id)


asyncio.run(main())

tuesday.py, a new process with a different model:

async def main() -> None:
    agent = DefaultAgent.from_markdown(
        "care_navigator.md",
        model=<model_client_claude>,
        state_path=".agentlane/care-navigator.json",
    )
    result = await agent.run("Patient 4471 feels lightheaded this morning. What now?")
    print(agent.agent_id)  # same address as Monday
    print(result.final_output)  # knows about yesterday's lisinopril

Nothing was passed between the two scripts except the state file. The agent's identity, conversation, and turn count live with the agent. The model, the process, and the run loop are supplied fresh each time. Swap state_path= for your own StateStore when a file is not enough, and bind the agent to a distributed runtime when it needs to live on a worker. Same agent, same address.

Why AgentLane

Most agent frameworks start with a prompt, a few tools, and a loop. AgentLane starts one layer lower. Every agent has an identity, a job, permissions, tools, state, and a place in the system. Some agents are long-lived employees with ongoing responsibilities. Others are temporary contractors that fan out, do their part, and go away. Both talk to each other the same way: through addressed messages.

That gives you three things:

  1. State stays with whoever owns it. Review status, user preferences, and conversation history belong to the agent or task that owns them, not to one chat transcript.
  2. You can see what happened. Which agent got the task, which worker ran it, which messages and tools were involved, and what came back.
  3. Local grows into distributed. The agent you run in one process today can run on a pool of workers tomorrow. The way agents talk to each other does not change.

Install

uv add agentlane

Add a provider or integration as an extra:

uv add "agentlane[openai]"            # OpenAI Responses client (default provider)
uv add "agentlane[litellm]"           # any model LiteLLM supports
uv add "agentlane[claude-agent-sdk]"  # Claude Agent SDK coworkers
uv add "agentlane[braintrust]"        # export traces to Braintrust

Working from a checkout of this repo:

uv sync --all-extras

Quick start

An agent is a markdown file. The frontmatter is the config and the body is the system prompt. The two steps below build on each other: the same agent goes from a single file to a team on a distributed runtime. The model and the run loop never change.

Both steps share one model client:

import asyncio
import os

from agentlane_openai import ResponsesClient

from agentlane.harness.agents import DefaultAgent
from agentlane.models import Config

model = ResponsesClient(
    config=Config(api_key=os.environ["OPENAI_API_KEY"], model="gpt-5.4-mini"),
)

1. An agent from a markdown file

care_navigator.md:

---
name: care-navigator
description: Guides patients to a clear next step for a new symptom or concern.
---
You are a concise patient care navigation agent. Give one clear next step. When
a clinical tool is available, use it before advising on a medication.
async def main() -> None:
    agent = DefaultAgent.from_markdown("care_navigator.md", model=model)
    result = await agent.run(
        "I feel dizzy after starting a new blood-pressure medication. What first?"
    )
    print(result.final_output)


asyncio.run(main())

One file, one run(...). By default it runs on a local single-threaded runtime, and every run leaves resumable state on the agent. Add state_path= to keep that state across processes, as in See it.

2. A team on a distributed runtime

Add a specialist with subagents= and bind both to a distributed runtime. The specialist becomes an addressed agent the lead can delegate to, and the runtime can later move it onto its own worker.

med_safety.md:

---
name: med-safety
description: Use to check a medication for interactions and safety flags before advising.
model: inherit
---
You review a medication for interactions and safety flags, and return a short
note that says clearly when something is urgent.
from agentlane.runtime import distributed_runtime


async def main() -> None:
    async with distributed_runtime() as runtime:
        agent = DefaultAgent.from_markdown(
            "care_navigator.md",
            model=model,
            subagents=["med_safety.md"],
            runtime=runtime,
        )
        result = await agent.run(
            "I started lisinopril yesterday and feel lightheaded. Is that expected?"
        )
        print(result.final_output)


asyncio.run(main())

The lead calls med_safety as a tool, gets the note back, and answers. model: inherit lets the specialist reuse the lead's model.

Markdown is the fast path. When you need real Python tools, tuned model calls, or run-loop limits, build an AgentDescriptor directly. Any plain function can be a tool, with no decorator or registration. See Default Agents, Markdown Agent Definitions, and Distributed Agents.

Connect other harnesses

An AgentLane address does not need an AgentLane model loop behind it. Anything bound to the runtime as a Task can receive addressed work.

Claude Agent SDK coworker. Give a Claude identity an address on the runtime. A native AgentLane agent sends it a task the usual way and uses the reply in its own run.

from agentlane_claude_agent_sdk import ClaudeAgent
from agentlane.messaging import AgentId

claude = AgentId.from_values("claude-sdk", "analyst")
ClaudeAgent.bind(runtime, claude)

outcome = await runtime.send_message(
    "Summarize the interaction risks for lisinopril.",
    sender=lead_id,
    recipient=claude,
)

Every addressed task starts a fresh SDK session. See Harness Tasks and the coworker example.

TypeScript app shells. @agentlanejs/process-bridge starts a local Python AgentLane backend as a child process and streams typed session events over stdio. See Process Bridge.

Layers

Use them together or pick the one you need.

Layer What it does Start here
Runtime agent identity, execution, scheduling, local and distributed workers Engine and Execution · Distributed Runtime
Messaging addressed sends, pub/sub, delivery outcomes, per-recipient ordering Routing and Delivery
Models prompt templates, schemas, structured output, native tools, provider clients Overview · Prompt Templating
Harness DefaultAgent, markdown definitions, resumable and persistent state, handoffs, sub-agents, shims, skills, compaction Default Agents · Architecture
Transport wire-safe serialization across process boundaries Serialization
Tracing spans and metrics across runtime, model, and harness Tracing Overview

Provider and integration packages live under packages/: agentlane-openai, agentlane-litellm, agentlane-claude-agent-sdk, agentlane-braintrust, agentlane-process-bridge, and @agentlanejs/process-bridge.

Development

/usr/bin/make format
/usr/bin/make lint
/usr/bin/make tests

Run a single test:

uv run pytest -s -k <test_name>

Contributing

The website is a separate static Astro project. Edit its Markdown/MDX content under website/src/content/. Use make -C website install and make -C website dev to run it. It has its own Makefile and CI and is excluded from Python and npm releases.

  1. Keep changes small and focused.
  2. Add or update tests when behavior changes.
  3. Update the public docs and examples when the developer-facing surface changes.
  4. Make sure formatting, linting, and tests pass before you open a PR.

License

MIT

Metadata

Release files for agentlane 0.17.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 agentlane 0.17.0
File Size Uploaded
agentlane-0.17.0.tar.gz 1.4 MB Details

Built distribution (wheel)

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

Total release size: 1.8 MB

Release files / agentlane-0.17.0.tar.gz

Download URL agentlane-0.17.0.tar.gz
Size 1.4 MB
Tags Source
SHA-256 checksum
How to use checksums
8e7e943d220d2521439969eab3a5c2c063148b275fef6a2110dd7d19ab542134
BLAKE2b-256 checksum
How to use checksums
e239e60e613b4c7ad048e970360706799e9568b15a780edbda1bb16b487af11b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / agentlane-0.17.0-py3-none-any.whl

Download URL agentlane-0.17.0-py3-none-any.whl
Size 356.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9be905cbfbf2273c6c930bb6be62c5f1d9edcf0a3b01cb3cef99688c975246a6
BLAKE2b-256 checksum
How to use checksums
0aaae838715f3dd0597f0ec65e14912a35a3405379046157d0e2522103b52282
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.19.0

2 release files

This release

0.17.0 This release

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

1 release file

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