Skip to main content

DeepHarness logo
DeepHarness

Compose LLM agents into typed, concurrent workflows.

A lightweight framework for wiring plain Python functions — and the agents inside them — into a graph that runs branches in parallel, routes on conditions, and threads one typed state object through the whole thing.

Python 3.11+ PyPI Dependencies: httpx only Async native Ruff License: MIT Read the docs

Install · Quickstart · Graphs · Providers · Docs · Contributing


Why DeepHarness

  • One dependency. That's it. httpx. Providers talk to vendor REST APIs directly — no vendor SDKs, no transitive dependency sprawl.
  • Your state is a dataclass. Not an untyped dict. Your editor autocompletes it, your type checker checks it.
  • Nodes are just functions. Sync or async, decorated in place. No base class to inherit, no runner object to construct.
  • Parallel by default. Independent branches run concurrently via asyncio; sync functions are offloaded to threads so a blocking call never stalls the event loop.
  • One provider interface, a dozen vendors. OpenAI, Anthropic, Gemini, and OpenAI-compatible gateways (Groq, Together, Fireworks, DeepSeek, Mistral, Cerebras, OpenRouter, XAI, Ollama, LMStudio, VLLM) all share the same LLM interface.

Install

pip install deepharness

Or from source:

pip install git+https://github.com/sayedshaun/deepharness.git

Requires Python 3.11 or newer.

Quickstart

An Agent runs a think/act loop against a model: ask for a response, dispatch any tool calls it requests, repeat until the model answers with no tool calls.

from deepharness import Agent, OpenAI, tool


@tool
def get_weather(city: str) -> str:
    """Look up the current weather for a city."""
    return f"It is 22°C and sunny in {city}."


agent = Agent(
    OpenAI(model="gpt-4o-mini"),  # reads OPENAI_API_KEY from the environment
    tools=[get_weather],
)

result = agent.run("Weather in Oslo?")
print(result.output)

Every entry point comes in both flavours — run() / arun() and stream() / astream() — so the same agent drops into a script or an event loop unchanged:

result = await agent.arun("Weather in Oslo?")

Agents as tools

An Agent can itself be handed to another agent as a tool via as_tool(), so one agent can delegate a task to another:

researcher = Agent(OpenAI(model="gpt-4o-mini"), name="researcher")

editor = Agent(
    OpenAI(model="gpt-4o-mini"),
    name="editor",
    tools=[researcher.as_tool(description="Look up facts on a topic.")],
)

Graphs

For fixed, known-shape workflows — run these steps, some in parallel, then merge — wire plain functions (or agents) into a Graph instead:

import asyncio
from dataclasses import dataclass

from deepharness import Graph


@dataclass
class State:
    sales: str = ""
    churn: str = ""
    summary: str = ""


graph = Graph(State)


@graph.add(start=True)
async def fetch_sales(state: State) -> State:
    await asyncio.sleep(0.5)
    state.sales = "Sales up 12% QoQ."
    return state


@graph.add(start=True)
async def fetch_churn(state: State) -> State:
    await asyncio.sleep(0.3)
    state.churn = "Churn down to 4%."
    return state


@graph.add(end=True)
def summarize(state: State) -> State:
    state.summary = f"{state.sales} {state.churn}"
    return state


graph.connect(fetch_sales, summarize)
graph.connect(fetch_churn, summarize)

executor = graph.build()
result = asyncio.run(executor.run())

print(result.summary)  # Sales up 12% QoQ. Churn down to 4%.

fetch_sales and fetch_churn both run in the first wave, concurrently. summarize waits for both before running.

Agent or Graph?

Reach for as_tool() when an LLM should decide at runtime whether and which sub-agent to call. Reach for Graph when the workflow's shape — which steps, which run in parallel, in what order — is known ahead of time.

Providers

Pass api_key= explicitly, or leave it out and let the provider read its own environment variable:

Provider Environment variable
OpenAI OPENAI_API_KEY
Anthropic ANTHROPIC_API_KEY
Gemini GEMINI_API_KEY or GOOGLE_API_KEY

OpenAI-compatible gateways each read their own key — GROQ_API_KEY, TOGETHER_API_KEY, DEEPSEEK_API_KEY, and so on — and local runtimes (Ollama, LMStudio, VLLM) need no key at all. Swapping vendors means swapping the constructor; nothing else changes:

from deepharness import Anthropic, Gemini, Groq, Ollama

Anthropic(model="claude-sonnet-4-5")
Gemini(model="gemini-2.5-flash")
Groq(model="llama-3.3-70b-versatile")
Ollama(model="llama3.2")  # no key needed

Contributing

Issues and pull requests are welcome. To get a working checkout:

git clone https://github.com/sayedshaun/deepharness.git
cd deepharness
pip install -e ".[dev]"
make test

Two conventions are worth knowing before you open a pull request:

  • The dependency budget is one. httpx, and nothing else at runtime. A feature that needs a third-party library almost always has a standard-library shape — reach for that instead.
  • Tests must not touch the network. Inject an httpx client or transport so the suite stays deterministic and offline.

Run make fmt and make test before pushing; CI runs the same checks on Python 3.11, 3.12 and 3.13. Keep each commit focused on a single change, with a one-line message prefixed by a Conventional Commits type (feat:, fix:, docs:, and so on).

Full setup, commands, and design conventions live in CONTRIBUTING.md; the rules the code itself is held to are in AGENTS.md.

License

Released under the MIT License — Copyright (c) 2026 Sayed Shaun.

You may use, modify, distribute, and sell this software, in open-source or commercial work, provided the copyright notice and licence text travel with it. It comes with no warranty.


Simple, modular, typed, dependency-light.

Metadata

Release files for deepharness 0.2.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 deepharness 0.2.0
File Size Uploaded
deepharness-0.2.0.tar.gz 60.7 kB Details

Built distribution (wheel)

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

Total release size: 108.7 kB

Release files / deepharness-0.2.0.tar.gz

Download URL deepharness-0.2.0.tar.gz
Size 60.7 kB
Tags Source
SHA-256 checksum
How to use checksums
41bffefddfc0b132e57ad5d8451d7d0d69b4fa1cfd3fda1626f9286c6653c45f
BLAKE2b-256 checksum
How to use checksums
761549e24ce9f388a6566183a08a8fd73bc64d50e084614a346bda13685768da
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 Sep 4, 2026.

Transparency log

Release files / deepharness-0.2.0-py3-none-any.whl

Download URL deepharness-0.2.0-py3-none-any.whl
Size 47.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
58f3824c7fca179202fdfd06b7101a37b22a7ac10b9ae9fc74e622e500867e7a
BLAKE2b-256 checksum
How to use checksums
de31443d32b181fd3458281d3685c7d747aeb933ab899cab29924a5fdc66223c
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 Sep 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

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