From 10ed8ef90e7ddae5ecbb73049f6a8ed200a6406b Mon Sep 17 00:00:00 2001 From: dgenio Date: Mon, 9 Mar 2026 06:05:09 +0000 Subject: [PATCH 1/2] docs: rewrite README hero section for 30-second clarity Resolves #66 - Add one-line tagline, badges (PyPI, CI, Python, license), Mermaid before/after diagram, and minimal quickstart code snippet - Move Problem/Solution narrative into 'Why ChainWeaver?' section - Promote Installation to top-level section - Merge comparison table into Why section (remove duplicate at bottom) - Fix Architecture tree: logging.py -> log_utils.py --- README.md | 84 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 8a8cef4..0190781 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,47 @@ # ChainWeaver -**Deterministic orchestration layer for MCP-based agents.** +**Compile deterministic MCP tool chains into LLM-free executable flows.** + +[![PyPI](https://img.shields.io/pypi/v/chainweaver)](https://pypi.org/project/chainweaver/) +[![CI](https://github.com/dgenio/ChainWeaver/actions/workflows/ci.yml/badge.svg)](https://github.com/dgenio/ChainWeaver/actions/workflows/ci.yml) +[![Python](https://img.shields.io/pypi/pyversions/chainweaver)](https://pypi.org/project/chainweaver/) +[![License](https://img.shields.io/github/license/dgenio/ChainWeaver)](LICENSE) + +```mermaid +flowchart LR + subgraph before ["❌ Naive Agent Chaining · N LLM calls"] + R1([Request]) --> L1[LLM] --> T1[Tool A] --> L2[LLM] --> T2[Tool B] --> L3[LLM] --> T3[Tool C] + end + subgraph after ["✅ ChainWeaver · 0 LLM calls"] + R2([Request]) --> E[FlowExecutor] --> U1[Tool A] --> U2[Tool B] --> U3[Tool C] + end +``` + +```python +from chainweaver import Tool, Flow, FlowStep, FlowRegistry, FlowExecutor + +# 1. Wrap any function as a schema-validated Tool +double = Tool(name="double", description="Doubles a number.", + input_schema=NumberInput, output_schema=ValueOutput, fn=double_fn) +# 2. Wire tools into a Flow +flow = Flow(name="calc", description="Double a number.", + steps=[FlowStep(tool_name="double", input_mapping={"number": "number"})]) +# 3. Register and execute — zero LLM calls +registry = FlowRegistry() +registry.register_flow(flow) +executor = FlowExecutor(registry=registry) +executor.register_tool(double) +result = executor.execute_flow("calc", {"number": 5}) +# result.final_output → {"number": 5, "value": 10} +``` + +> See the [full example](#quick-start) below or run `python examples/simple_linear_flow.py` -> *Compiled execution graphs, not interpreted reasoning.* +**[Installation](#installation) · [Why ChainWeaver?](#why-chainweaver) · [Quick Start](#quick-start) · [Architecture](#architecture) · [Roadmap](#roadmap)** --- -## The Problem +## Why ChainWeaver? When an LLM-powered agent chains tools together — `fetch_data → transform → store` — a common pattern is to insert an LLM call between *every* step so the model can "decide" @@ -35,10 +70,8 @@ previous output) these intermediate LLM calls add: - **Cost** — every call consumes tokens and credits. - **Unpredictability** — a language model might route differently on each invocation. -## The Solution - ChainWeaver compiles deterministic multi-tool chains into **executable flows** that run -without any LLM involvement between steps. +without any LLM involvement between steps: ``` User request @@ -52,23 +85,28 @@ Response Think of it as the difference between an **interpreter** and a **compiler**: -| Naive agent chaining | ChainWeaver flow | -|------------------------------|------------------------------------| -| Interpreted, step by step | Compiled, graph-first | -| LLM decides each next action | Execution is pre-wired | -| Non-deterministic by default | Deterministic by design | -| Cost scales with steps | Fixed overhead per flow invocation | +| Criterion | Naive LLM chaining | ChainWeaver | +|---|---|---| +| LLM calls per step | 1 per step | 0 | +| Latency | O(n × LLM RTT) | O(n × tool RTT) | +| Cost | O(n × token cost) | Fixed infra cost | +| Reproducibility | Non-deterministic | Deterministic | +| Schema validation | Ad-hoc / none | Pydantic enforced | +| Observability | Prompt logs only | Structured step logs | +| Reusability | Prompt templates | Registered, versioned flows | --- -## Quick Start - -### Installation +## Installation ```bash pip install chainweaver ``` +--- + +## Quick Start + ### Define tools, build a flow, and execute it ```python @@ -178,7 +216,7 @@ chainweaver/ ├── registry.py # FlowRegistry — in-memory flow catalogue ├── executor.py # FlowExecutor — deterministic, LLM-free runner ├── exceptions.py # Typed exceptions with traceable context -└── logging.py # Structured per-step logging +└── log_utils.py # Structured per-step logging ``` ### Core abstractions @@ -344,20 +382,6 @@ All exceptions inherit from `ChainWeaverError`. --- -## Comparison: Naive Agent Chaining vs ChainWeaver - -| Criterion | Naive LLM chaining | ChainWeaver | -|---|---|---| -| LLM calls per step | 1 per step | 0 | -| Latency | O(n × LLM RTT) | O(n × tool RTT) | -| Cost | O(n × token cost) | Fixed infra cost | -| Reproducibility | Non-deterministic | Deterministic | -| Schema validation | Ad-hoc / none | Pydantic enforced | -| Observability | Prompt logs only | Structured step logs | -| Reusability | Prompt templates | Registered, versioned flows | - ---- - ## Development ```bash From 2259908bf69adb7527fd27c8bc9e24f84fdb8af2 Mon Sep 17 00:00:00 2001 From: dgenio Date: Mon, 9 Mar 2026 13:41:18 +0000 Subject: [PATCH 2/2] Add hint comment to hero snippet for undefined names --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0190781..fd34670 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ flowchart LR ```python from chainweaver import Tool, Flow, FlowStep, FlowRegistry, FlowExecutor +# (NumberInput, ValueOutput, double_fn defined in full example below) # 1. Wrap any function as a schema-validated Tool double = Tool(name="double", description="Doubles a number.",