agentflowkit 0.1.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. agentflowkit-0.4.0/.coverage +0 -0
  2. agentflowkit-0.4.0/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
  3. agentflowkit-0.4.0/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
  4. agentflowkit-0.4.0/.github/workflows/ci.yml +81 -0
  5. agentflowkit-0.4.0/.github/workflows/docs.yml +32 -0
  6. agentflowkit-0.4.0/.github/workflows/publish.yml +33 -0
  7. agentflowkit-0.4.0/.gitignore +21 -0
  8. agentflowkit-0.4.0/CHANGELOG.md +111 -0
  9. agentflowkit-0.4.0/CONTRIBUTING.md +99 -0
  10. agentflowkit-0.4.0/PKG-INFO +428 -0
  11. agentflowkit-0.4.0/README.md +388 -0
  12. agentflowkit-0.4.0/benchmarks/parallel_speedup.py +71 -0
  13. agentflowkit-0.4.0/docs/getting-started.md +83 -0
  14. agentflowkit-0.4.0/docs/guides/cost-streaming.md +48 -0
  15. agentflowkit-0.4.0/docs/guides/memory.md +195 -0
  16. agentflowkit-0.4.0/docs/guides/observability.md +52 -0
  17. agentflowkit-0.4.0/docs/guides/tools.md +58 -0
  18. agentflowkit-0.4.0/docs/index.md +42 -0
  19. agentflowkit-0.4.0/docs/reference.md +49 -0
  20. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/examples/code_reviewer.py +1 -2
  21. agentflowkit-0.4.0/examples/cpp_build_pipeline.py +293 -0
  22. agentflowkit-0.4.0/examples/market_analysis_crew.py +258 -0
  23. agentflowkit-0.4.0/examples/memory_chat_agents.py +172 -0
  24. agentflowkit-0.4.0/examples/notebooks/parallel_execution_demo.ipynb +292 -0
  25. agentflowkit-0.4.0/examples/notebooks/quickstart.ipynb +269 -0
  26. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/examples/research_crew.py +2 -3
  27. agentflowkit-0.4.0/examples/research_react_agent.py +146 -0
  28. agentflowkit-0.4.0/examples/streaming_and_cost.py +52 -0
  29. agentflowkit-0.4.0/examples/tool_agent.py +66 -0
  30. agentflowkit-0.4.0/mkdocs.yml +66 -0
  31. agentflowkit-0.4.0/pyproject.toml +83 -0
  32. agentflowkit-0.4.0/src/agentflow/__init__.py +68 -0
  33. agentflowkit-0.4.0/src/agentflow/agent.py +372 -0
  34. agentflowkit-0.4.0/src/agentflow/cache.py +131 -0
  35. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/src/agentflow/events.py +3 -2
  36. agentflowkit-0.4.0/src/agentflow/exceptions.py +45 -0
  37. agentflowkit-0.4.0/src/agentflow/llm.py +249 -0
  38. agentflowkit-0.4.0/src/agentflow/logging.py +131 -0
  39. agentflowkit-0.4.0/src/agentflow/memory.py +322 -0
  40. agentflowkit-0.4.0/src/agentflow/observability.py +91 -0
  41. agentflowkit-0.4.0/src/agentflow/pipeline.py +340 -0
  42. agentflowkit-0.4.0/src/agentflow/pricing.py +57 -0
  43. agentflowkit-0.4.0/src/agentflow/py.typed +0 -0
  44. agentflowkit-0.4.0/src/agentflow/rate_limiter.py +73 -0
  45. agentflowkit-0.4.0/src/agentflow/tools.py +154 -0
  46. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/src/agentflow/types.py +24 -3
  47. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/tests/test_agent.py +1 -1
  48. agentflowkit-0.4.0/tests/test_cache.py +140 -0
  49. agentflowkit-0.4.0/tests/test_conditional.py +124 -0
  50. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/tests/test_llm.py +0 -2
  51. agentflowkit-0.4.0/tests/test_logging.py +72 -0
  52. agentflowkit-0.4.0/tests/test_long_term_memory.py +440 -0
  53. agentflowkit-0.4.0/tests/test_memory.py +264 -0
  54. agentflowkit-0.4.0/tests/test_observability.py +99 -0
  55. agentflowkit-0.4.0/tests/test_parallel.py +242 -0
  56. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/tests/test_pipeline.py +3 -5
  57. agentflowkit-0.4.0/tests/test_pricing.py +36 -0
  58. agentflowkit-0.4.0/tests/test_rate_limiter.py +57 -0
  59. agentflowkit-0.4.0/tests/test_retry.py +46 -0
  60. agentflowkit-0.4.0/tests/test_streaming.py +54 -0
  61. agentflowkit-0.4.0/tests/test_tools.py +231 -0
  62. agentflowkit-0.1.0/.gitignore +0 -11
  63. agentflowkit-0.1.0/PKG-INFO +0 -177
  64. agentflowkit-0.1.0/README.md +0 -149
  65. agentflowkit-0.1.0/pyproject.toml +0 -46
  66. agentflowkit-0.1.0/src/agentflow/__init__.py +0 -25
  67. agentflowkit-0.1.0/src/agentflow/agent.py +0 -97
  68. agentflowkit-0.1.0/src/agentflow/exceptions.py +0 -21
  69. agentflowkit-0.1.0/src/agentflow/llm.py +0 -96
  70. agentflowkit-0.1.0/src/agentflow/pipeline.py +0 -170
  71. agentflowkit-0.1.0/tmpclaude-0006-cwd +0 -1
  72. agentflowkit-0.1.0/tmpclaude-07af-cwd +0 -1
  73. agentflowkit-0.1.0/tmpclaude-153f-cwd +0 -1
  74. agentflowkit-0.1.0/tmpclaude-186c-cwd +0 -1
  75. agentflowkit-0.1.0/tmpclaude-1ebb-cwd +0 -1
  76. agentflowkit-0.1.0/tmpclaude-2838-cwd +0 -1
  77. agentflowkit-0.1.0/tmpclaude-2ebe-cwd +0 -1
  78. agentflowkit-0.1.0/tmpclaude-6962-cwd +0 -1
  79. agentflowkit-0.1.0/tmpclaude-6b68-cwd +0 -1
  80. agentflowkit-0.1.0/tmpclaude-8083-cwd +0 -1
  81. agentflowkit-0.1.0/tmpclaude-80d4-cwd +0 -1
  82. agentflowkit-0.1.0/tmpclaude-8eb0-cwd +0 -1
  83. agentflowkit-0.1.0/tmpclaude-94d9-cwd +0 -1
  84. agentflowkit-0.1.0/tmpclaude-a787-cwd +0 -1
  85. agentflowkit-0.1.0/tmpclaude-aea4-cwd +0 -1
  86. agentflowkit-0.1.0/tmpclaude-ba42-cwd +0 -1
  87. agentflowkit-0.1.0/tmpclaude-c025-cwd +0 -1
  88. agentflowkit-0.1.0/tmpclaude-c7b8-cwd +0 -1
  89. agentflowkit-0.1.0/tmpclaude-de78-cwd +0 -1
  90. agentflowkit-0.1.0/tmpclaude-de86-cwd +0 -1
  91. agentflowkit-0.1.0/tmpclaude-e628-cwd +0 -1
  92. agentflowkit-0.1.0/tmpclaude-e792-cwd +0 -1
  93. agentflowkit-0.1.0/tmpclaude-f142-cwd +0 -1
  94. agentflowkit-0.1.0/tmpclaude-f2e4-cwd +0 -1
  95. agentflowkit-0.1.0/tmpclaude-f501-cwd +0 -1
  96. agentflowkit-0.1.0/tmpclaude-fd1d-cwd +0 -1
  97. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/.gitattributes +0 -0
  98. {agentflowkit-0.1.0 → agentflowkit-0.4.0}/LICENSE +0 -0
Binary file
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a reproducible bug in agentflowkit
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear, concise description of the bug.
12
+
13
+ ## Reproduction Steps
14
+
15
+ ```python
16
+ # Minimal reproducible example
17
+ from agentflow import Agent, LLM, Pipeline
18
+
19
+ @Agent(name="example", role="Example")
20
+ async def example(task: str, context: dict) -> str:
21
+ return task
22
+
23
+ # Code that triggers the bug
24
+ ```
25
+
26
+ ## Expected Behavior
27
+
28
+ What you expected to happen.
29
+
30
+ ## Actual Behavior
31
+
32
+ What actually happened (include full traceback if applicable).
33
+
34
+ ## Environment
35
+
36
+ - `agentflowkit` version: <!-- e.g. 0.2.0 -->
37
+ - Python version: <!-- e.g. 3.11.5 -->
38
+ - OS: <!-- e.g. Ubuntu 22.04 / macOS 14 / Windows 11 -->
39
+ - LLM provider: <!-- e.g. OpenAI, Groq, Ollama -->
40
+
41
+ ## Additional Context
42
+
43
+ Any other context, screenshots, or logs that may help diagnose the issue.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature or improvement
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ What problem does this feature solve? Who is affected?
12
+
13
+ ## Proposed Solution
14
+
15
+ A clear description of what you want to happen.
16
+
17
+ ```python
18
+ # Ideally, show what the API would look like
19
+ pipe = Pipeline(llm=llm)
20
+ pipe.add(agent, new_feature_param=...)
21
+ ```
22
+
23
+ ## Alternatives Considered
24
+
25
+ Other approaches you considered and why you prefer this one.
26
+
27
+ ## Additional Context
28
+
29
+ Links to related issues, prior art in other frameworks (LangChain, CrewAI, etc.), or references.
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint & Type Check
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+
21
+ - name: Install dev dependencies
22
+ run: pip install -e ".[dev]"
23
+
24
+ - name: Run ruff
25
+ run: ruff check src/ tests/ examples/ benchmarks/
26
+
27
+ - name: Run mypy
28
+ run: mypy src/agentflow/
29
+
30
+ test:
31
+ name: Tests (Python ${{ matrix.python-version }})
32
+ runs-on: ubuntu-latest
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ python-version: ["3.10", "3.11", "3.12"]
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Set up Python ${{ matrix.python-version }}
42
+ uses: actions/setup-python@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+
46
+ - name: Install dependencies
47
+ run: pip install -e ".[dev]"
48
+
49
+ - name: Run tests with coverage
50
+ run: pytest tests/ -v --cov=agentflow --cov-report=xml --cov-report=term-missing
51
+
52
+ - name: Upload coverage to Codecov
53
+ uses: codecov/codecov-action@v4
54
+ with:
55
+ file: ./coverage.xml
56
+ fail_ci_if_error: false
57
+ env:
58
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
59
+
60
+ build:
61
+ name: Build Distribution
62
+ runs-on: ubuntu-latest
63
+ needs: [lint, test]
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+
67
+ - name: Set up Python
68
+ uses: actions/setup-python@v5
69
+ with:
70
+ python-version: "3.11"
71
+
72
+ - name: Install build tools
73
+ run: pip install build
74
+
75
+ - name: Build wheel and sdist
76
+ run: python -m build
77
+
78
+ - name: Check distributions
79
+ run: |
80
+ pip install twine
81
+ twine check dist/*
@@ -0,0 +1,32 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "docs/**"
8
+ - "mkdocs.yml"
9
+ - "src/**"
10
+ - ".github/workflows/docs.yml"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: write
15
+
16
+ jobs:
17
+ deploy:
18
+ name: Build & Deploy MkDocs
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.11"
27
+
28
+ - name: Install docs dependencies
29
+ run: pip install -e ".[docs]"
30
+
31
+ - name: Build and deploy to GitHub Pages
32
+ run: mkdocs gh-deploy --force
@@ -0,0 +1,33 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ name: Publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ environment: release
13
+ permissions:
14
+ id-token: write # Required for OIDC trusted publishing
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.11"
23
+
24
+ - name: Install build tools
25
+ run: pip install build
26
+
27
+ - name: Build distribution
28
+ run: python -m build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
32
+ # No API key needed — uses OIDC trusted publishing
33
+ # Configure at: https://pypi.org/manage/project/agentflowkit/settings/publishing/
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ venv/
9
+ .env
10
+ .pytest_cache/
11
+ *.egg
12
+ # AI assistants / agents
13
+ .claude/
14
+ CLAUDE.md
15
+ .cursor/
16
+ .cursorrules
17
+ .aider*
18
+ .github/copilot-instructions.md
19
+ AGENTS.md
20
+ chat.md
21
+ tmpclaude-*
@@ -0,0 +1,111 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented here.
4
+
5
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [0.3.0]
11
+
12
+ ### Added
13
+ - **Tool / function calling** (`tools.py`): the `@tool` decorator turns any sync
14
+ or async Python function into an LLM-callable tool. Argument JSON schemas are
15
+ generated automatically from type hints via Pydantic. Agents given `tools=[...]`
16
+ run a bounded **ReAct loop** (call → execute tools → observe → repeat) up to
17
+ `max_tool_iterations` (default 6). Tool errors are fed back to the model for
18
+ recovery. New `ToolError` exception; tool-call traces recorded in
19
+ `AgentResult.metadata["tool_calls"]`.
20
+ - **Cost tracking** (`pricing.py`): built-in USD price tables for common OpenAI
21
+ and Anthropic models with longest-prefix matching. `LLM.generate()` returns a
22
+ `cost` (and `prompt_tokens`/`completion_tokens`); `AgentResult.cost` and
23
+ `PipelineResult.total_cost` aggregate spend. Cache hits bill `0.0`.
24
+ `register_price()` / `estimate_cost()` are public.
25
+ - **Token streaming**: `LLM.astream()` yields content deltas token-by-token for
26
+ interactive UIs (honours the rate limiter; no cache/retry mid-stream).
27
+ - **Observability hooks** (`observability.py`): `Hooks` base class + `LoggingHooks`
28
+ wire the previously-unused `PipelineLogger` into `Pipeline.run()` (which was
29
+ silent before). A raising hook is caught and warned, never crashing the run.
30
+ - **Production-grade retry**: unified exponential backoff with jitter and
31
+ `Retry-After` header support. New `LLM(retry_base_delay=, retry_jitter=)` args.
32
+ - **Documentation site**: MkDocs Material + mkdocstrings under `docs/`, deployed
33
+ via a new `docs.yml` workflow. New `docs` optional-dependency group.
34
+ - New examples: `tool_agent.py`, `streaming_and_cost.py`; and
35
+ `benchmarks/parallel_speedup.py`.
36
+
37
+ ### Fixed
38
+ - **`py.typed` marker** added — the package advertised `Typing :: Typed` but
39
+ shipped no marker, so downstream type-checkers saw no types.
40
+ - **Red CI made green**: resolved 1 `ruff` error (B904) and 7 `mypy --strict`
41
+ errors across `llm.py`, `cache.py`, `logging.py`, `events.py`, `pipeline.py`.
42
+
43
+ ### Changed
44
+ - `__version__` bumped to `0.3.0`.
45
+ - Test coverage raised to ~91%; `fail_under` tightened from 80 → 90.
46
+ - `Pipeline.__init__` gains a `hooks` parameter; `run()` now emits lifecycle
47
+ events and generates `run_id` up front.
48
+
49
+ ---
50
+
51
+ ## [0.2.0]
52
+
53
+ ### Added
54
+ - **Parallel execution**: Agents at the same DAG level now run concurrently via
55
+ `asyncio.gather()`. `_resolve_levels()` replaces `_resolve_order()` and uses
56
+ Kahn's algorithm to group independent agents.
57
+ - **Per-agent timeout**: `Pipeline.add(timeout=N)` wraps each agent coroutine with
58
+ `asyncio.wait_for`; raises `AgentTimeoutError` on expiry.
59
+ - **Conditional branching**: `Pipeline.add(condition=lambda ctx: ...)` allows
60
+ dynamic skipping of agents based on upstream outputs. Skipped agents emit
61
+ `agent_skipped` events in streaming mode.
62
+ - **Pipeline-level retry**: `Pipeline(retry_failed_agents=N)` retries failed
63
+ agents up to N times with exponential backoff (1s, 2s, 4s). Timeouts are
64
+ non-retriable.
65
+ - **LLM response caching** (`cache.py`): `ResponseCache` ABC with `InMemoryCache`
66
+ (SHA-256 key, lazy TTL eviction, max-size LRU) and `RedisCache` (optional dep).
67
+ Cache is wired into `LLM(cache=...)`.
68
+ - **Rate limiting** (`rate_limiter.py`): `RateLimiter(requests_per_minute, max_concurrent)`
69
+ using `asyncio.Semaphore` + sliding-window counter. Async context manager interface.
70
+ Wired into `LLM(rate_limiter=...)`.
71
+ - **Structured logging** (`logging.py`): `PipelineLogger` (LoggerAdapter with JSON
72
+ formatter) carrying `run_id` and `pipeline` through all log records.
73
+ - **Agent output validation**: `@Agent(output_schema=MyPydanticModel)` validates
74
+ LLM response JSON against a Pydantic v2 model; raises `AgentOutputValidationError`
75
+ on failure.
76
+ - New exception classes: `AgentTimeoutError`, `AgentOutputValidationError`.
77
+ - `AgentResult` gains: `cached`, `level`, `timestamp` fields.
78
+ - `PipelineResult` gains: `run_id`, `levels_executed`, `agents_with_cache_hits` fields.
79
+ - `Event.type` now documents all valid values including `"agent_skipped"`.
80
+ - GitHub Actions CI workflow (lint, test matrix py3.10-3.12, codecov, build check).
81
+ - GitHub Actions publish workflow (OIDC trusted publishing on version tags).
82
+ - Issue templates for bug reports and feature requests.
83
+ - `CONTRIBUTING.md` with development setup and PR checklist.
84
+ - `pythonpath = ["src"]` in pytest config to fix editable install on non-ASCII paths.
85
+
86
+ ### Changed
87
+ - `__version__` bumped to `0.2.0`.
88
+ - `pipeline.py`: `Pipeline.__init__` gains `retry_failed_agents` parameter.
89
+ - `pipeline.py`: `Pipeline.add` gains `timeout` and `condition` parameters.
90
+ - `llm.py`: `LLM.__init__` gains `cache` and `rate_limiter` parameters.
91
+ Return dict from `generate()` now includes `"cached"` key.
92
+ - `pyproject.toml`: classifier updated to Beta; dev extras expanded;
93
+ `ruff`, `mypy`, `coverage` tool config sections added.
94
+
95
+ ### Performance
96
+ - Two independent agents that each take 0.1s now complete in ~0.1s (parallel),
97
+ not ~0.2s (sequential).
98
+
99
+ ---
100
+
101
+ ## [0.1.0] — 2026-02-27
102
+
103
+ ### Added
104
+ - Initial release.
105
+ - `@Agent` decorator and `BaseAgent` ABC for defining agents.
106
+ - `Pipeline` with topological sort (`_resolve_order`) for dependency resolution.
107
+ - `LLM` provider abstraction with OpenAI-compatible API, retry logic.
108
+ - `EventEmitter` + `pipeline.stream()` for async event streaming.
109
+ - Pydantic v2 data models: `AgentResult`, `PipelineResult`, `Event`.
110
+ - Custom exception hierarchy: `AgentFlowError`, `AgentError`, `LLMError`, `PipelineError`.
111
+ - Published to PyPI as `agentflowkit`.
@@ -0,0 +1,99 @@
1
+ # Contributing to agentflowkit
2
+
3
+ Thank you for your interest in contributing! This guide explains how to work on the project.
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/KaramQ6/agentflow.git
9
+ cd agentflow
10
+ pip install -e ".[dev]"
11
+ ```
12
+
13
+ Verify your setup:
14
+
15
+ ```bash
16
+ pytest tests/ -v
17
+ ```
18
+
19
+ All tests should pass before you start making changes.
20
+
21
+ ## Project Structure
22
+
23
+ ```
24
+ src/agentflow/
25
+ ├── agent.py # @Agent decorator + BaseAgent ABC
26
+ ├── cache.py # ResponseCache, InMemoryCache, RedisCache
27
+ ├── events.py # EventEmitter for streaming
28
+ ├── exceptions.py # Exception hierarchy
29
+ ├── llm.py # LLM provider abstraction
30
+ ├── logging.py # PipelineLogger (structured JSON)
31
+ ├── pipeline.py # Pipeline DAG orchestration (core)
32
+ ├── rate_limiter.py # RateLimiter (RPM + concurrency)
33
+ └── types.py # Pydantic data models
34
+ ```
35
+
36
+ ## Code Style
37
+
38
+ We use **ruff** for linting + formatting and **mypy** for type checking.
39
+
40
+ ```bash
41
+ ruff check src/ tests/ # Lint
42
+ ruff format src/ tests/ # Format
43
+ mypy src/agentflow/ # Type check
44
+ ```
45
+
46
+ All code must:
47
+ - Have full type hints
48
+ - Pass `ruff check` with no errors
49
+ - Pass `mypy` in strict mode
50
+
51
+ ## Adding a Feature
52
+
53
+ ### New cache backend
54
+
55
+ 1. Subclass `ResponseCache` in `cache.py`
56
+ 2. Implement `async get(key)` and `async set(key, value, ttl)`
57
+ 3. Add to `__all__` in `__init__.py`
58
+ 4. Write tests in `tests/test_cache.py`
59
+
60
+ ### New exception type
61
+
62
+ 1. Add to `exceptions.py` (subclass the appropriate parent)
63
+ 2. Add to `__all__` in `__init__.py`
64
+ 3. Import and use in the relevant module
65
+
66
+ ### New pipeline feature
67
+
68
+ 1. Add to `pipeline.py` — keep changes localized to `_PipelineNode`, `Pipeline.add()`, or the execution loop
69
+ 2. Emit appropriate events for streaming consumers
70
+ 3. Write tests in `tests/test_parallel.py` or a new test file
71
+
72
+ ## Pull Request Checklist
73
+
74
+ - [ ] Tests added for new functionality
75
+ - [ ] All existing tests still pass (`pytest tests/ -v`)
76
+ - [ ] Type hints on all new functions and classes
77
+ - [ ] Docstrings on public API additions
78
+ - [ ] Entry added to `[Unreleased]` section in `CHANGELOG.md`
79
+ - [ ] No new dependencies added without discussion in an issue first
80
+
81
+ ## Commit Message Convention
82
+
83
+ We use [Conventional Commits](https://www.conventionalcommits.org/):
84
+
85
+ ```
86
+ feat: add Redis cache backend
87
+ fix: handle asyncio.TimeoutError in _execute_node
88
+ docs: add caching section to README
89
+ test: add parallel execution timing test
90
+ refactor: extract _resolve_levels from _resolve_order
91
+ ```
92
+
93
+ ## Running the Full Suite
94
+
95
+ ```bash
96
+ pytest tests/ -v --cov=agentflow --cov-report=term-missing
97
+ ```
98
+
99
+ Coverage should remain ≥ 80%.