Skip to main content

Mash

CI PyPI Python versions License: Apache-2.0

Mash is a self-hosted durable runtime for code-authored automations using workflows with agents. A workflow is an ordered pipeline of typed steps, a step is deterministic Python or one run of a harnessed agent, and control flow stays in code.

Mash gives you a Python AgentSpec contract for defining agents, a WorkflowSpec for authoring step pipelines, a HostBuilder that composes both into a deployable pool, a FastAPI server for deployment, and a CLI/API for interacting with a running host.

It's designed around Host-to-Agent Protocol (H2A) that standardizes interactions between user applications and agents.

What Mash Provides

  • Workflows: ordered pipelines of typed steps, durable and observable. A step is deterministic Python or one agent run; each step's output threads into the next step's input with schema checks at every edge. The pipeline is code you can read, diff, test, and replay.
  • Agent harness: the agent loop runs inside a durable request engine with tools, skills, memory, and structured output. Requests are recorded as replayable runtime events; retries, restarts, and long-running work just work.
  • Frontier and open-source models: built-in adapters for Anthropic, OpenAI, and Gemini, and any open-source model served over a Chat Completions endpoint, self-hosted with vLLM or Ollama or hosted on OpenRouter. Each agent picks its model in one line of build_llm().
  • Self-hosted interfaces: HTTP API with streaming, CLI, and interactive REPL, all on one Postgres. Deploy locally, in Docker, or on any cloud.
  • Multi-agent composition: define a primary agent, add specialized subagents, and compose workflows behind a single host. Agents delegate to each other without a separate coordination layer.
  • Human-in-the-loop: agents can pause for approval or ask users questions mid-execution. Interactions survive host restarts.
  • Observability: span trees, trace analysis, telemetry API, built-in dashboard, and CLI trace inspection. No external APM needed.
  • Synthetic evals: generate a test dataset and scoring rubric from a host's declared capabilities, run experiments that snapshot the live host, and compare quality and cost across runs before the first user message. Datasets, rubrics, and experiment results live in the built-in dashboard.
                  ┌─────────────────────────────────────────┐
                  │          Durable Request                │
                  │                                         │
                  │   ┌─ context ─── memory ──┐             │
                  │   │                       │             │
request ────────► │   │     Agent Loop        │ ──► signals │
(cli/api)         │   │ think → act → observe │      │      │
                  │   │                       │      ▼      │
                  │   └─ tools ───── skills ──┘  structured │
workflow step ──► │        ▲                      output    │
(api/cli)         │        │ user interaction               │
                  │        ▼ (approval / ask-user)          │
                  │                                         │
                  │       resumable · replayable            │
                  └─────────────────────────────────────────┘

A request from a user and a step in a workflow ride the same durable loop.

See Mash under the hood for a deeper look at each capability, and the product brief for the pitch.

Quick Start

Install:

# install the library
uv add mashpy

# install the `mash` CLI on your PATH
uv tool install mashpy 

Define your agents:

Each agent is an AgentSpec subclass. It names itself, picks an LLM, and declares a system prompt, tools, skills and agent config.

## my_app/agents.py

from mash import AgentSpec
from mash.core.config import AgentConfig
from mash.core.llm import AnthropicProvider
from mash.skills import SkillRegistry
from mash.tools import ToolRegistry


class ConciergeAgent(AgentSpec):
    def get_agent_id(self):
        return "concierge"

    def build_tools(self):
        return ToolRegistry()

    def build_skills(self):
        return SkillRegistry()

    def build_llm(self):
        return AnthropicProvider(app_id="concierge")

    def build_agent_config(self):
        return AgentConfig(
            app_id="concierge",
            system_prompt=(
                "You are the concierge. Answer the user directly, and "
                "delegate research-heavy questions to the research subagent."
            ),
        )


class ResearchAgent(AgentSpec):
    def get_agent_id(self):
        return "research"

    def build_tools(self):
        return ToolRegistry()

    def build_skills(self):
        return SkillRegistry()

    def build_llm(self):
        return AnthropicProvider(app_id="research")

    def build_agent_config(self):
        return AgentConfig(
            app_id="research",
            system_prompt="You handle research-heavy questions in depth.",
        )

Author the workflow:

The workflow is the automation: an ordered pipeline of typed steps that code owns end to end. Use a CodeStep for deterministic Python and an AgentStep when the work needs an agent.

## my_app/workflows.py

from pydantic import BaseModel

from mash import AgentStep, CodeStep, StepContext, WorkflowSpec


class ResearchRequest(BaseModel):
    topic: str


class ResearchPlan(BaseModel):
    topic: str
    questions: list[str]


class ResearchBrief(BaseModel):
    summary: str
    sources: list[str]


def plan_research(
    request: ResearchRequest,
    _context: StepContext,
) -> ResearchPlan:
    return ResearchPlan(
        topic=request.topic,
        questions=[
            f"What are the key facts about {request.topic}?",
            f"What should a reader understand about {request.topic}?",
        ],
    )


RESEARCH_BRIEF = WorkflowSpec(
    workflow_id="research-brief",
    input_model=ResearchRequest,
    steps=[
        CodeStep(
            step_id="plan",
            run=plan_research,
            input=ResearchRequest,
            output=ResearchPlan,
        ),
        AgentStep(
            step_id="research",
            agent_id="research",
            input=ResearchPlan,
            output=ResearchBrief,
        ),
    ],
)

The CodeStep output becomes the AgentStep input. Mash validates both edges, runs each step durably, and uses the last step's output as the workflow result.

Build the pool:

The pool is the unit of deploy: agents and workflows registered together.

## my_app/host.py

from mash import AgentMetadata, HostBuilder

from .agents import ConciergeAgent, ResearchAgent
from .workflows import RESEARCH_BRIEF


def build_pool():
    pool = (
        HostBuilder()
        .agent(
            ConciergeAgent(),
            metadata=AgentMetadata(
                display_name="Concierge",
                description="Front-door agent that answers users and delegates.",
                capabilities=["conversation", "delegation"],
                usage_guidance="Default entry point for user requests.",
            ),
        )
        .agent(
            ResearchAgent(),
            metadata=AgentMetadata(
                display_name="Research",
                description="Handles research-heavy questions in depth.",
                capabilities=["research", "analysis"],
                usage_guidance="Use for questions that need digging.",
            ),
        )
        .workflow(RESEARCH_BRIEF)
        .build()
    )
    return pool

A pool can also be workflows alone. A workflow of pure CodeSteps references no agents, and the resulting pool serves only workflow runs:

def build_pool():
    # EXPORT_METRICS is a WorkflowSpec of pure CodeSteps; no agents needed.
    return HostBuilder().workflow(EXPORT_METRICS).build()

Configure the environment:

The host needs an LLM key and a Postgres URL for its durable runtime. Put them in a .env file the host loads on start:

# .env
ANTHROPIC_API_KEY=sk-ant-...
MASH_DATABASE_URL=postgresql://user:pass@localhost:5432/mash

Start the host:

mash host serve --host-app my_app.host:build_pool --host 127.0.0.1 --port 8000

Browse available agents:

mash browse

Compose an assistant host with primary and subagents:

mash compose --host assistant --primary concierge --subagents research \
  --workflows research-brief

Talk to the host or execute / commands using Mash repl:

mash repl --host assistant

Key Concepts

Concept What it is
AgentSpec Abstract contract defining one agent (id, tools, skills, LLM, config)
HostBuilder Fluent builder that composes agents, workflows, and hosts into a Pool
Pool The deployed pool of role-less agents the API server runs
Host A composition over the pool (primary + subagents + workflows), defined in code or dynamically over the API
ToolRegistry Register callable tools; built-ins include Bash, AskUser, InvokeSubagent
SkillRegistry Markdown instruction bundles loaded on demand via a meta-tool
LLMProvider Adapters for Anthropic, OpenAI, and Gemini
OSSCompatibleProvider Runs open-source models (Gemma, Qwen, DeepSeek) over any Chat Completions endpoint, self-hosted (vLLM, Ollama) or hosted (OpenRouter); chosen in build_llm() like any provider
WorkflowSpec Ordered pipeline of typed steps (CodeStep / AgentStep); runs are durable and observable
Eval / Experiment A generated dataset and rubric bound to a host; an experiment runs the dataset against the host, snapshots its composition, and scores results with an LLM judge

Mushy / Thoughts

See the agent's original exposed thought summaries in Admin → Activity → Thoughts. Filter by Agent and scroll the latest 50 traces with nonempty summaries. Underlined phrases bring out the language's personality; selecting one moves Mushy beside the passage. Each trace links to its Admin logs.

Capture is always enabled for runtime agents when their provider supports it (currently Gemini). The trace sidebar in Logs links directly to that trace's thoughts, including older traces. There is no separate interpreter, GIF generation API, or public sharing surface. See Mushy and Pilot.

Mash Pilot

Pilot is a command-line guide to the Mash codebase, built on the Mash SDK and shipped in this repo at src/pilot/. Its agents specialize in Mash's own modules — so instead of reading docs or grepping the source, you ask Pilot and it answers from the actual source tree. It also ships the pilot-changelog workflow and the build-mash-agent/build-mash-workflow/ build-mash-host scaffolding skills.

docker run -d --name pilot -p 8000:8000 \
  -e GEMINI_API_KEY=... -e OPENROUTER_API_KEY=sk-or-... \
  -v pilot-data:/var/lib/pilot ghcr.io/imsid/mashpy-pilot:latest

curl -fsSL https://raw.githubusercontent.com/imsid/mashpy/main/install.sh | sh
pilot repl --host guide

See src/pilot/README.md for the guide team, the required keys and model overrides, the shipped workflow, and scaffolding your own app.

Build with a Coding Agent

This repo includes CLAUDE.md so coding agents like Claude Code, Codex, and Cursor can scaffold a Mash-powered agent from a natural language prompt. Copy it into your project or point your agent at this repo to get started. The Pilot guide (above) also carries the build-mash-agent, build-mash-workflow, and build-mash-host skills for interactive scaffolding from the REPL.

Documentation

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup, tests, and the pull request flow, and SECURITY.md for reporting vulnerabilities. Release notes live in CHANGELOG.md.

License

Mash is licensed under the Apache License 2.0.

Metadata

Release files for mashpy 0.23.2

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

Source distribution (sdist)

Source distribution for mashpy 0.23.2
File Size Uploaded
mashpy-0.23.2.tar.gz 905.7 kB Details

Built distribution (wheel)

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

Total release size: 1.9 MB

Release files / mashpy-0.23.2.tar.gz

Download URL mashpy-0.23.2.tar.gz
Size 905.7 kB
Tags Source
SHA-256 checksum
How to use checksums
788af622bb1307911a0d6cfa62988fab978fb4fa44ad55b17aad40f266216f6b
BLAKE2b-256 checksum
How to use checksums
d655a94452c268e43a9020092abda7f1e5b2f1b327785ce1d78a72ef55413a6a
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 11, 2026.

Transparency log

Release files / mashpy-0.23.2-py3-none-any.whl

Download URL mashpy-0.23.2-py3-none-any.whl
Size 978.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
531814a66fcd2650ce3cb6d4fc6156e36dfd9e3dafc625acf385a1b83a1123ea
BLAKE2b-256 checksum
How to use checksums
9f2399cce68c482b73ae7fc0f9313c487daa388923a38fdbc221701331ca8185
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.23.2 This release

2 release files

0.22.1

2 release files

0.21.1

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.18.1

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.12

2 release files

0.6.11

2 release files

0.6.10

2 release files

0.6.9

2 release files

0.6.8

2 release files

0.6.7

2 release files

0.6.6

2 release files

0.6.5

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.0

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

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