Skip to main content

Open-source multi-agent AI orchestration. Chain agents, manage state, handle failures — without 800 lines of boilerplate.

Project description

n00dles 🍜

PyPI

Open-source multi-agent AI orchestration. Chain agents, manage state, handle failures — without 800 lines of boilerplate.

from n00dles import agent, pipeline, run

@agent(model="claude-sonnet-4-6")
def researcher(topic: str) -> str:
    """Research the topic. Return 3 key facts."""

@agent(model="claude-sonnet-4-6")
def writer(research: str) -> str:
    """Write a short article from the research."""

content_pipeline = pipeline(researcher >> writer, retry=3)
result = run(content_pipeline, topic="multi-agent orchestration")
print(result.output)

Install

pip install get-n00dles

(the PyPI distribution name is get-n00dles — PyPI rejected the bare n00dles as too visually similar to an existing package; the import is still import n00dles)

Set an API key for whichever provider you're using (n00dles wraps litellm, so any provider litellm supports works — Anthropic, OpenAI, Mistral, Gemini, Ollama, and more):

export ANTHROPIC_API_KEY="sk-ant-..."

Why n00dles

  • No magic. Every behavior is traceable from your code to the LLM call in a handful of stack frames. No metaclasses, no hidden registries.
  • Reliable by default. Retry with exponential backoff, per-node timeouts, and checkpointed state are built in — not opt-in extras.
  • One provider layer. Wraps litellm instead of maintaining five parallel provider SDKs. Switch models with a string, not a rewrite.
  • Zero cloud dependency. This package makes no network calls except to your LLM provider. No telemetry, no license checks, no phone-home.

Core concepts

Agents are plain functions decorated with @agent. The docstring becomes the system prompt; the type hints become the I/O contract:

@agent(model="claude-haiku-4-5")
def classify(ticket: str) -> str:
    """Classify the support ticket as billing, technical, or other."""

Pipelines chain agents with >> and wrap the chain with pipeline() to attach retry/timeout policy:

support_flow = pipeline(classify >> respond, retry=3, timeout=60)
result = run(support_flow, ticket="My invoice is wrong")

run() returns a RunResult:

result.output          # the final agent's return value
result.run_id           # unique id — pass to a future resume() call if interrupted
result.duration_ms      # wall-clock time for the whole run
result.total_tokens     # summed across every agent call, including retries
result.agent_traces     # per-agent timing, status, and token usage, in order

State is checkpointed to SQLite after every node by default — no config required. If your agent's return type is a Pydantic model instead of str, n00dles instructs the LLM to respond in JSON and validates the response against your schema, raising AgentOutputError if it doesn't fit.

from n00dles import configure

configure(state_store="sqlite:///my_app.db")   # custom path (default: ./n00dles_state.db)
configure(trace_exporter="otel")               # pip install get-n00dles[otel]

Parallel execution runs agents concurrently with | or parallel(). The next step receives a dict keyed by each member's function name — match your downstream agent's parameter names to those keys and there's no manual merging:

from n00dles import parallel

@agent(model="gpt-4o")
def scrape_news(query: str) -> str: """Scrape latest news."""

@agent(model="gpt-4o")
def scrape_twitter(query: str) -> str: """Pull recent posts."""

@agent(model="claude-sonnet-4-6")
def merge_signals(scrape_news: str, scrape_twitter: str) -> str:
    """Merge and rank both signals."""

intel = pipeline(parallel(scrape_news, scrape_twitter) >> merge_signals, timeout=20)
result = run(intel, query="AI regulation 2026")

parallel(*agents, max_concurrency=None) caps how many run at once; without it, every member runs simultaneously.

Conditional routing sends execution to exactly one agent with branch(), based on a key read off the previous step's output — the string itself if it's plain str, or the category field if it's a dict or Pydantic model:

from n00dles import branch

triage = pipeline(classify >> branch(billing=handle_billing, support=handle_support, default=handle_support))
result = run(triage, ticket="My invoice is wrong")

An unmatched key with no default raises BranchError.

What's in this release (v0.2.0)

  • @agent, pipeline(), >>, run()/arun()
  • parallel() / branch() / the | operator for fan-out and conditional routing
  • litellm provider integration (every major LLM provider)
  • Retry with exponential backoff + jitter, per-node timeouts, fallback agents
  • SQLite state store (default) with checkpoint-and-resume (including partial-resume for parallel groups)
  • Pydantic I/O validation for structured agent outputs
  • Trace events + an optional OpenTelemetry exporter (pip install get-n00dles[otel])

Not yet implemented (tracked for the next release — see PUBLISHING.md for the full rollout plan):

  • Circuit breaker
  • Redis state backend
  • Langfuse and Helicone exporters
  • mock_agent() / MockLLM testing utilities
  • The noodles CLI (run, serve, deploy)

Development

git clone https://github.com/n00dlehouse/n00dles-py
cd n00dles-py
pip install -e ".[dev]"
pytest
ruff check .

Tests run entirely against an in-repo fake provider — no API keys or network access required.

License

MIT

Project details


Download files

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

Source Distribution

get_n00dles-0.2.0.tar.gz (27.3 kB view details)

Uploaded Source

Built Distribution

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

get_n00dles-0.2.0-py3-none-any.whl (22.4 kB view details)

Uploaded Python 3

File details

Details for the file get_n00dles-0.2.0.tar.gz.

File metadata

  • Download URL: get_n00dles-0.2.0.tar.gz
  • Upload date:
  • Size: 27.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for get_n00dles-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6b2f6e9fe08c82908822788adb09edddfdf8d682aa1bfb5248512521c92c02c6
MD5 c70d1f7370520623625567f153b9f6be
BLAKE2b-256 28d53a6f080b6a7f67548d98dfa286e72bc2e6d6c6db62cefaabfe970c598ad3

See more details on using hashes here.

File details

Details for the file get_n00dles-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: get_n00dles-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for get_n00dles-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5a459ac1dfe8d526fedc64797483cd2a860dc1330014a31301011a816cb4e3a9
MD5 94a0d2e58e8966b04e496fdd8505f06c
BLAKE2b-256 a555424b811f44e69ca2373b58620ad1676d68a57ca0008c25122cf09eb379ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page