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

  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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentlane-0.15.0.tar.gz (1.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentlane-0.15.0-py3-none-any.whl (339.0 kB view details)

Uploaded Python 3

File details

Details for the file agentlane-0.15.0.tar.gz.

File metadata

  • Download URL: agentlane-0.15.0.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agentlane-0.15.0.tar.gz
Algorithm Hash digest
SHA256 0a42457cf21e802d62929f03b0b800e0042a102a42ed643690c6256d0819ec1c
MD5 111d4dfe8e4a5c745c255184050d5aeb
BLAKE2b-256 9c1d661e0bda2a729de3474f63d706a30bf813ca8dc1150c9deed43b3a13b268

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentlane-0.15.0.tar.gz:

Publisher: pypi-publish.yml on yasik/agentlane

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agentlane-0.15.0-py3-none-any.whl.

File metadata

  • Download URL: agentlane-0.15.0-py3-none-any.whl
  • Upload date:
  • Size: 339.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agentlane-0.15.0-py3-none-any.whl
Algorithm Hash digest
SHA256 079291f7ed6f17e4cbab538522c4b98a1d25a5490f1b1d5ba55d0e03c6aceb16
MD5 bdd77b42fdf3b641e44f7bbaf791612b
BLAKE2b-256 c7e52e16a2269cfbeee1033dce692338edf2a5878e7032a0d521b854858d6c99

See more details on using hashes here.

Provenance

The following attestation bundles were made for agentlane-0.15.0-py3-none-any.whl:

Publisher: pypi-publish.yml on yasik/agentlane

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.15.0 This release

2 files

0.14.0

2 files

0.13.1

2 files

0.13.0

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.1

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

1 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