cannyforge 0.2.0__tar.gz → 0.3.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 (67) hide show
  1. cannyforge-0.3.0/PKG-INFO +282 -0
  2. cannyforge-0.3.0/README.md +238 -0
  3. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/__init__.py +8 -1
  4. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/adapters/__init__.py +1 -0
  5. cannyforge-0.3.0/cannyforge/adapters/autoresearch.py +341 -0
  6. cannyforge-0.3.0/cannyforge/adapters/langgraph.py +445 -0
  7. cannyforge-0.3.0/cannyforge/bundled_skills/fsi-workflow/SKILL.md +67 -0
  8. cannyforge-0.3.0/cannyforge/bundled_skills/tool-use/SKILL.md +106 -0
  9. cannyforge-0.3.0/cannyforge/bundled_skills/tool-use/assets/templates.yaml +43 -0
  10. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/core.py +87 -3
  11. cannyforge-0.3.0/cannyforge/corrections.py +259 -0
  12. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/knowledge.py +319 -4
  13. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/learning.py +113 -16
  14. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/llm.py +26 -2
  15. cannyforge-0.3.0/cannyforge.egg-info/PKG-INFO +282 -0
  16. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge.egg-info/SOURCES.txt +13 -0
  17. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge.egg-info/requires.txt +4 -0
  18. {cannyforge-0.2.0 → cannyforge-0.3.0}/pyproject.toml +3 -1
  19. cannyforge-0.3.0/tests/test_bench_fsi80.py +66 -0
  20. cannyforge-0.3.0/tests/test_core_portability.py +78 -0
  21. cannyforge-0.3.0/tests/test_corrections.py +117 -0
  22. cannyforge-0.3.0/tests/test_eval_trace.py +337 -0
  23. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_knowledge.py +112 -1
  24. cannyforge-0.3.0/tests/test_langgraph_adapter.py +382 -0
  25. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_learning.py +3 -0
  26. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_llm.py +49 -0
  27. cannyforge-0.3.0/tests/test_scenario_harness.py +275 -0
  28. cannyforge-0.3.0/tests/test_tool_use_skill.py +146 -0
  29. cannyforge-0.2.0/PKG-INFO +0 -472
  30. cannyforge-0.2.0/README.md +0 -431
  31. cannyforge-0.2.0/cannyforge.egg-info/PKG-INFO +0 -472
  32. {cannyforge-0.2.0 → cannyforge-0.3.0}/LICENSE +0 -0
  33. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/adapters/crewai.py +0 -0
  34. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/adapters/langchain.py +0 -0
  35. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/calendar-manager/SKILL.md +0 -0
  36. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/calendar-manager/assets/templates.yaml +0 -0
  37. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/content-summarizer/SKILL.md +0 -0
  38. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/email-writer/SKILL.md +0 -0
  39. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/email-writer/assets/templates.yaml +0 -0
  40. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/bundled_skills/web-searcher/SKILL.md +0 -0
  41. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/cli.py +0 -0
  42. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/dashboard.py +0 -0
  43. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/demo.py +0 -0
  44. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/export.py +0 -0
  45. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/mcp_server.py +0 -0
  46. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/registry.py +0 -0
  47. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/__init__.py +0 -0
  48. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/crm_service.py +0 -0
  49. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/email_service.py +0 -0
  50. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/mock_calendar_mcp.py +0 -0
  51. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/service_base.py +0 -0
  52. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/slack_service.py +0 -0
  53. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/services/web_search_api.py +0 -0
  54. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/skills.py +0 -0
  55. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/storage.py +0 -0
  56. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/tools.py +0 -0
  57. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge/workers.py +0 -0
  58. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge.egg-info/dependency_links.txt +0 -0
  59. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge.egg-info/entry_points.txt +0 -0
  60. {cannyforge-0.2.0 → cannyforge-0.3.0}/cannyforge.egg-info/top_level.txt +0 -0
  61. {cannyforge-0.2.0 → cannyforge-0.3.0}/setup.cfg +0 -0
  62. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_declarative_skill.py +0 -0
  63. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_integration.py +0 -0
  64. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_production.py +0 -0
  65. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_skill_loader.py +0 -0
  66. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_spec_compliance.py +0 -0
  67. {cannyforge-0.2.0 → cannyforge-0.3.0}/tests/test_tools.py +0 -0
@@ -0,0 +1,282 @@
1
+ Metadata-Version: 2.4
2
+ Name: cannyforge
3
+ Version: 0.3.0
4
+ Summary: Self-improving agents with closed-loop learning — agents that learn to get it right
5
+ License: BSL-1.1
6
+ Project-URL: Homepage, https://github.com/cannyforge/cannyforge
7
+ Project-URL: Documentation, https://github.com/cannyforge/cannyforge#readme
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: python-dotenv>=1.0.0
19
+ Requires-Dist: requests>=2.31.0
20
+ Requires-Dist: pydantic>=2.5.0
21
+ Requires-Dist: pyyaml>=6.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
25
+ Provides-Extra: claude
26
+ Requires-Dist: anthropic>=0.39.0; extra == "claude"
27
+ Provides-Extra: openai
28
+ Requires-Dist: openai>=1.0.0; extra == "openai"
29
+ Provides-Extra: deepseek
30
+ Requires-Dist: openai>=1.0.0; extra == "deepseek"
31
+ Provides-Extra: langgraph
32
+ Requires-Dist: langgraph>=0.2.0; extra == "langgraph"
33
+ Provides-Extra: mcp
34
+ Requires-Dist: mcp[cli]>=1.0.0; extra == "mcp"
35
+ Provides-Extra: dashboard
36
+ Requires-Dist: streamlit>=1.30.0; extra == "dashboard"
37
+ Provides-Extra: all
38
+ Requires-Dist: anthropic>=0.39.0; extra == "all"
39
+ Requires-Dist: openai>=1.0.0; extra == "all"
40
+ Requires-Dist: langgraph>=0.2.0; extra == "all"
41
+ Requires-Dist: mcp[cli]>=1.0.0; extra == "all"
42
+ Requires-Dist: streamlit>=1.30.0; extra == "all"
43
+ Dynamic: license-file
44
+
45
+ # CannyForge
46
+
47
+ **Reliability memory for tool-using LLM agents.**
48
+
49
+ CannyForge watches your agent make mistakes, learns corrections, and injects them as SystemMessages before each LLM call. Your agent gets better over time — no retraining required.
50
+
51
+ ```
52
+ Agent makes errors → CannyForge learns corrections → Agent stops repeating them
53
+ ```
54
+
55
+ ![CannyForge demo: 80% → 100% on real LLM](docs/demo.gif)
56
+
57
+ ## Quick Start (LangGraph)
58
+
59
+ ```python
60
+ from cannyforge import CannyForge
61
+ from cannyforge.adapters.langgraph import CannyForgeMiddleware
62
+ from langgraph.prebuilt import create_react_agent
63
+
64
+ forge = CannyForge()
65
+ middleware = CannyForgeMiddleware(forge)
66
+ agent = create_react_agent(model, tools,
67
+ pre_model_hook=middleware.before_model,
68
+ post_model_hook=middleware.after_model)
69
+
70
+ # Just run tasks. CannyForge records errors via after_model.
71
+ # After learning, before_model injects corrections as SystemMessages.
72
+ ```
73
+
74
+ ## v0.3 Direction
75
+
76
+ The benchmark branch is focused on three adoption-oriented improvements:
77
+
78
+ - better reliability loops for tool-using agents
79
+ - broader benchmark coverage for arguments, multi-step execution, and recovery
80
+ - portable learned skills for assistant and workflow reuse
81
+
82
+ This is aimed at modern agent stacks, including LangGraph, LangChain-style tool agents,
83
+ CrewAI-style orchestration, MCP-connected assistants, and personal assistant workflows.
84
+
85
+ See [docs/v0.3-public.md](/home/xiwei/pg/cannyforge/docs/v0.3-public.md) for the public summary.
86
+
87
+ ## How It Works
88
+
89
+ 1. **Record errors** — `after_model` detects tool failures and records them
90
+ 2. **Learn corrections** — `run_learning_cycle()` clusters errors and generates specific correction text (template or LLM-generated)
91
+ 3. **Inject corrections** — `before_model` prepends a SystemMessage with all active corrections before each LLM call
92
+ 4. **Track effectiveness** — corrections that prevent recurrence are kept; ineffective ones can be regenerated
93
+
94
+ The correction is specific and actionable:
95
+ ```
96
+ [CANNYFORGE] Learned rules for this request:
97
+ - When the task involves report, summary, sales, use `generate_report`, NOT `get_data`.
98
+ Example: "Create a summary of Q4 sales performance"
99
+ ```
100
+
101
+ ## Demo: 60% → 100% on Real LLM
102
+
103
+ ```bash
104
+ pip install langgraph langchain-openai
105
+ # Set LLM_API_KEY in .env
106
+ python scenarios/demo_cannyforge.py
107
+ ```
108
+
109
+ This runs 15 ambiguous tool-selection tasks twice:
110
+ - **Phase 1**: baseline without corrections — records errors
111
+ - **Learning**: generates corrections from observed errors
112
+ - **Phase 2**: same tasks with correction injection — accuracy improves
113
+
114
+ Real output with DeepSeek:
115
+ ```
116
+ Phase 1 accuracy: 9/15 (60%)
117
+ Phase 2 accuracy: 15/15 (100%)
118
+ Tasks fixed:
119
+ - Restart the staging server -> execute_action
120
+ - Send an alert to the on-call team -> execute_action
121
+ - Deploy the latest build to production -> execute_action
122
+ - Create a summary of Q4 sales performance -> generate_report
123
+ - Write up a status report for this sprint -> generate_report
124
+ - Generate a monthly uptime report -> generate_report
125
+ ```
126
+
127
+ No simulated errors. No hand-crafted rules. Real LLM decisions, real corrections from the pipeline.
128
+
129
+ ## Install
130
+
131
+ ```bash
132
+ pip install cannyforge # from PyPI
133
+ ```
134
+
135
+ Or from source:
136
+ ```bash
137
+ git clone https://github.com/cannyforge/cannyforge.git
138
+ cd cannyforge
139
+ pip install -e .
140
+ ```
141
+
142
+ ## Scenarios
143
+
144
+ | Script | Purpose |
145
+ |--------|---------|
146
+ | `scenarios/demo_cannyforge.py` | **Canonical demo** — full pipeline: baseline → learn → improve |
147
+ | `scenarios/demo_langgraph_tool_use.py` | Minimal quickstart — 3-line integration |
148
+ | `scenarios/demo.py` | Animated terminal demo (internal skill system) |
149
+
150
+ Older demo scripts are in `scenarios/archive/` for reference.
151
+
152
+ ## Framework Coverage
153
+
154
+ | Surface | Current repo path |
155
+ |--------|-------------------|
156
+ | LangGraph middleware | `cannyforge/adapters/langgraph.py` |
157
+ | LangChain adapter | `cannyforge/adapters/langchain.py` |
158
+ | CrewAI adapter | `cannyforge/adapters/crewai.py` |
159
+ | MCP server | `cannyforge/mcp_server.py` |
160
+ | Bundled assistant skills | `cannyforge/bundled_skills/` |
161
+
162
+ CannyForge is designed to sit on top of existing agent frameworks rather than replace them.
163
+ The public focus for v0.3 is improved tool routing, argument quality, multi-step execution, and
164
+ reusable skills.
165
+
166
+ ## Core Architecture
167
+
168
+ ### Corrections Pipeline (LangGraph integration)
169
+
170
+ ```
171
+ cannyforge/corrections.py — Correction dataclass + CorrectionGenerator
172
+ cannyforge/adapters/langgraph.py — CannyForgeMiddleware (pre/post model hooks)
173
+ cannyforge/knowledge.py — KnowledgeBase stores corrections + rules
174
+ cannyforge/learning.py — PatternDetector + LearningEngine
175
+ cannyforge/core.py — CannyForge orchestrator
176
+ ```
177
+
178
+ **CorrectionGenerator** turns error clusters into actionable text:
179
+ - **Template mode** (no LLM): groups by `(wrong_tool, right_tool)`, extracts keywords, formats guidance
180
+ - **LLM mode**: sends error cluster to LLM asking for a generalized rule covering unseen tasks
181
+
182
+ **CannyForgeMiddleware** hooks into LangGraph's `create_react_agent`:
183
+ - `before_model`: injects always-on corrections + conditional rules as a SystemMessage
184
+ - `after_model`: records tool failures, tracks correction effectiveness
185
+
186
+ ### Internal Skill System
187
+
188
+ CannyForge also includes a declarative skill system for standalone use (without LangGraph):
189
+
190
+ - Skills defined via `SKILL.md` files ([AgentSkills.io](https://agentskills.io/specification) spec)
191
+ - Three-tier execution: custom handler → LLM multi-step → template fallback
192
+ - PATTERN_LIBRARY with condition-based rules for internal context signals
193
+ - Rule lifecycle: ACTIVE → PROBATION → DORMANT → resurrection
194
+
195
+ ```python
196
+ from cannyforge import CannyForge
197
+ forge = CannyForge()
198
+ result = forge.execute("Write an email about the 3 PM meeting")
199
+ ```
200
+
201
+ See `scenarios/demo.py` for the animated terminal demo of this path.
202
+
203
+ ## How Learning Works
204
+
205
+ ### 1. Error Recording
206
+
207
+ ```python
208
+ # Via middleware (automatic):
209
+ agent = create_react_agent(llm, tools, post_model_hook=middleware.after_model)
210
+
211
+ # Or manual:
212
+ forge.learning_engine.record_error(
213
+ skill_name="tool_use",
214
+ task_description="Create a Q4 summary",
215
+ error_type="WrongToolError",
216
+ error_message="Called get_data instead of generate_report",
217
+ context_snapshot={...},
218
+ )
219
+ ```
220
+
221
+ ### 2. Learning Cycle
222
+
223
+ ```python
224
+ metrics = forge.run_learning_cycle(min_frequency=2, min_confidence=0.3)
225
+ # Produces:
226
+ # - Condition-based rules (for internal skill system)
227
+ # - Corrections (for LangGraph injection)
228
+ ```
229
+
230
+ ### 3. Correction Injection
231
+
232
+ ```python
233
+ corrections = forge.knowledge_base.get_corrections("tool_use")
234
+ # [Correction(content="When task involves report, summary... use generate_report, NOT get_data")]
235
+
236
+ # Automatically injected by middleware.before_model() as a SystemMessage
237
+ ```
238
+
239
+ ## Run Tests
240
+
241
+ ```bash
242
+ pytest tests/ -v
243
+ ```
244
+
245
+ ## Project Structure
246
+
247
+ ```
248
+ cannyforge/
249
+ ├── cannyforge/
250
+ │ ├── core.py # CannyForge orchestrator
251
+ │ ├── corrections.py # Correction + CorrectionGenerator
252
+ │ ├── knowledge.py # KnowledgeBase, Rules, Conditions, Actions
253
+ │ ├── learning.py # PatternDetector, LearningEngine
254
+ │ ├── skills.py # Declarative skill system
255
+ │ ├── llm.py # LLM providers (Claude, OpenAI, DeepSeek)
256
+ │ ├── tools.py # Tool definitions and execution
257
+ │ ├── storage.py # Storage backends (JSON, SQLite)
258
+ │ └── adapters/
259
+ │ └── langgraph.py # LangGraph middleware (pre/post model hooks)
260
+
261
+ ├── scenarios/
262
+ │ ├── demo_cannyforge.py # Canonical demo (corrections pipeline)
263
+ │ ├── demo_langgraph_tool_use.py # Minimal quickstart
264
+ │ └── demo.py # Animated demo (internal skill system)
265
+
266
+ ├── tests/ # Test suite
267
+ └── skills/ # Built-in skill definitions (SKILL.md)
268
+ ```
269
+
270
+ ## Further Reading
271
+
272
+ - Blog post: [From Prompt Tweaks to Learning Machines: The Agent Skill Primitive](https://medium.com/@xiweizhou/from-prompt-tweaks-to-learning-machines-the-agent-skill-primitive-93c8fa9dec8c?sk=ac888430da699bce7b635456ae2b1166)
273
+
274
+ ## License
275
+
276
+ Licensed under [BSL 1.1](LICENSE). Free to use in production, but you may not offer CannyForge as a competing hosted service. Converts to Apache 2.0 on 2030-03-01. See LICENSE for full terms.
277
+
278
+ For commercial licensing inquiries: cannyforge@gmail.com
279
+
280
+ ---
281
+
282
+ **CannyForge** — Your agent makes fewer repeated mistakes over time, with measurable evidence.
@@ -0,0 +1,238 @@
1
+ # CannyForge
2
+
3
+ **Reliability memory for tool-using LLM agents.**
4
+
5
+ CannyForge watches your agent make mistakes, learns corrections, and injects them as SystemMessages before each LLM call. Your agent gets better over time — no retraining required.
6
+
7
+ ```
8
+ Agent makes errors → CannyForge learns corrections → Agent stops repeating them
9
+ ```
10
+
11
+ ![CannyForge demo: 80% → 100% on real LLM](docs/demo.gif)
12
+
13
+ ## Quick Start (LangGraph)
14
+
15
+ ```python
16
+ from cannyforge import CannyForge
17
+ from cannyforge.adapters.langgraph import CannyForgeMiddleware
18
+ from langgraph.prebuilt import create_react_agent
19
+
20
+ forge = CannyForge()
21
+ middleware = CannyForgeMiddleware(forge)
22
+ agent = create_react_agent(model, tools,
23
+ pre_model_hook=middleware.before_model,
24
+ post_model_hook=middleware.after_model)
25
+
26
+ # Just run tasks. CannyForge records errors via after_model.
27
+ # After learning, before_model injects corrections as SystemMessages.
28
+ ```
29
+
30
+ ## v0.3 Direction
31
+
32
+ The benchmark branch is focused on three adoption-oriented improvements:
33
+
34
+ - better reliability loops for tool-using agents
35
+ - broader benchmark coverage for arguments, multi-step execution, and recovery
36
+ - portable learned skills for assistant and workflow reuse
37
+
38
+ This is aimed at modern agent stacks, including LangGraph, LangChain-style tool agents,
39
+ CrewAI-style orchestration, MCP-connected assistants, and personal assistant workflows.
40
+
41
+ See [docs/v0.3-public.md](/home/xiwei/pg/cannyforge/docs/v0.3-public.md) for the public summary.
42
+
43
+ ## How It Works
44
+
45
+ 1. **Record errors** — `after_model` detects tool failures and records them
46
+ 2. **Learn corrections** — `run_learning_cycle()` clusters errors and generates specific correction text (template or LLM-generated)
47
+ 3. **Inject corrections** — `before_model` prepends a SystemMessage with all active corrections before each LLM call
48
+ 4. **Track effectiveness** — corrections that prevent recurrence are kept; ineffective ones can be regenerated
49
+
50
+ The correction is specific and actionable:
51
+ ```
52
+ [CANNYFORGE] Learned rules for this request:
53
+ - When the task involves report, summary, sales, use `generate_report`, NOT `get_data`.
54
+ Example: "Create a summary of Q4 sales performance"
55
+ ```
56
+
57
+ ## Demo: 60% → 100% on Real LLM
58
+
59
+ ```bash
60
+ pip install langgraph langchain-openai
61
+ # Set LLM_API_KEY in .env
62
+ python scenarios/demo_cannyforge.py
63
+ ```
64
+
65
+ This runs 15 ambiguous tool-selection tasks twice:
66
+ - **Phase 1**: baseline without corrections — records errors
67
+ - **Learning**: generates corrections from observed errors
68
+ - **Phase 2**: same tasks with correction injection — accuracy improves
69
+
70
+ Real output with DeepSeek:
71
+ ```
72
+ Phase 1 accuracy: 9/15 (60%)
73
+ Phase 2 accuracy: 15/15 (100%)
74
+ Tasks fixed:
75
+ - Restart the staging server -> execute_action
76
+ - Send an alert to the on-call team -> execute_action
77
+ - Deploy the latest build to production -> execute_action
78
+ - Create a summary of Q4 sales performance -> generate_report
79
+ - Write up a status report for this sprint -> generate_report
80
+ - Generate a monthly uptime report -> generate_report
81
+ ```
82
+
83
+ No simulated errors. No hand-crafted rules. Real LLM decisions, real corrections from the pipeline.
84
+
85
+ ## Install
86
+
87
+ ```bash
88
+ pip install cannyforge # from PyPI
89
+ ```
90
+
91
+ Or from source:
92
+ ```bash
93
+ git clone https://github.com/cannyforge/cannyforge.git
94
+ cd cannyforge
95
+ pip install -e .
96
+ ```
97
+
98
+ ## Scenarios
99
+
100
+ | Script | Purpose |
101
+ |--------|---------|
102
+ | `scenarios/demo_cannyforge.py` | **Canonical demo** — full pipeline: baseline → learn → improve |
103
+ | `scenarios/demo_langgraph_tool_use.py` | Minimal quickstart — 3-line integration |
104
+ | `scenarios/demo.py` | Animated terminal demo (internal skill system) |
105
+
106
+ Older demo scripts are in `scenarios/archive/` for reference.
107
+
108
+ ## Framework Coverage
109
+
110
+ | Surface | Current repo path |
111
+ |--------|-------------------|
112
+ | LangGraph middleware | `cannyforge/adapters/langgraph.py` |
113
+ | LangChain adapter | `cannyforge/adapters/langchain.py` |
114
+ | CrewAI adapter | `cannyforge/adapters/crewai.py` |
115
+ | MCP server | `cannyforge/mcp_server.py` |
116
+ | Bundled assistant skills | `cannyforge/bundled_skills/` |
117
+
118
+ CannyForge is designed to sit on top of existing agent frameworks rather than replace them.
119
+ The public focus for v0.3 is improved tool routing, argument quality, multi-step execution, and
120
+ reusable skills.
121
+
122
+ ## Core Architecture
123
+
124
+ ### Corrections Pipeline (LangGraph integration)
125
+
126
+ ```
127
+ cannyforge/corrections.py — Correction dataclass + CorrectionGenerator
128
+ cannyforge/adapters/langgraph.py — CannyForgeMiddleware (pre/post model hooks)
129
+ cannyforge/knowledge.py — KnowledgeBase stores corrections + rules
130
+ cannyforge/learning.py — PatternDetector + LearningEngine
131
+ cannyforge/core.py — CannyForge orchestrator
132
+ ```
133
+
134
+ **CorrectionGenerator** turns error clusters into actionable text:
135
+ - **Template mode** (no LLM): groups by `(wrong_tool, right_tool)`, extracts keywords, formats guidance
136
+ - **LLM mode**: sends error cluster to LLM asking for a generalized rule covering unseen tasks
137
+
138
+ **CannyForgeMiddleware** hooks into LangGraph's `create_react_agent`:
139
+ - `before_model`: injects always-on corrections + conditional rules as a SystemMessage
140
+ - `after_model`: records tool failures, tracks correction effectiveness
141
+
142
+ ### Internal Skill System
143
+
144
+ CannyForge also includes a declarative skill system for standalone use (without LangGraph):
145
+
146
+ - Skills defined via `SKILL.md` files ([AgentSkills.io](https://agentskills.io/specification) spec)
147
+ - Three-tier execution: custom handler → LLM multi-step → template fallback
148
+ - PATTERN_LIBRARY with condition-based rules for internal context signals
149
+ - Rule lifecycle: ACTIVE → PROBATION → DORMANT → resurrection
150
+
151
+ ```python
152
+ from cannyforge import CannyForge
153
+ forge = CannyForge()
154
+ result = forge.execute("Write an email about the 3 PM meeting")
155
+ ```
156
+
157
+ See `scenarios/demo.py` for the animated terminal demo of this path.
158
+
159
+ ## How Learning Works
160
+
161
+ ### 1. Error Recording
162
+
163
+ ```python
164
+ # Via middleware (automatic):
165
+ agent = create_react_agent(llm, tools, post_model_hook=middleware.after_model)
166
+
167
+ # Or manual:
168
+ forge.learning_engine.record_error(
169
+ skill_name="tool_use",
170
+ task_description="Create a Q4 summary",
171
+ error_type="WrongToolError",
172
+ error_message="Called get_data instead of generate_report",
173
+ context_snapshot={...},
174
+ )
175
+ ```
176
+
177
+ ### 2. Learning Cycle
178
+
179
+ ```python
180
+ metrics = forge.run_learning_cycle(min_frequency=2, min_confidence=0.3)
181
+ # Produces:
182
+ # - Condition-based rules (for internal skill system)
183
+ # - Corrections (for LangGraph injection)
184
+ ```
185
+
186
+ ### 3. Correction Injection
187
+
188
+ ```python
189
+ corrections = forge.knowledge_base.get_corrections("tool_use")
190
+ # [Correction(content="When task involves report, summary... use generate_report, NOT get_data")]
191
+
192
+ # Automatically injected by middleware.before_model() as a SystemMessage
193
+ ```
194
+
195
+ ## Run Tests
196
+
197
+ ```bash
198
+ pytest tests/ -v
199
+ ```
200
+
201
+ ## Project Structure
202
+
203
+ ```
204
+ cannyforge/
205
+ ├── cannyforge/
206
+ │ ├── core.py # CannyForge orchestrator
207
+ │ ├── corrections.py # Correction + CorrectionGenerator
208
+ │ ├── knowledge.py # KnowledgeBase, Rules, Conditions, Actions
209
+ │ ├── learning.py # PatternDetector, LearningEngine
210
+ │ ├── skills.py # Declarative skill system
211
+ │ ├── llm.py # LLM providers (Claude, OpenAI, DeepSeek)
212
+ │ ├── tools.py # Tool definitions and execution
213
+ │ ├── storage.py # Storage backends (JSON, SQLite)
214
+ │ └── adapters/
215
+ │ └── langgraph.py # LangGraph middleware (pre/post model hooks)
216
+
217
+ ├── scenarios/
218
+ │ ├── demo_cannyforge.py # Canonical demo (corrections pipeline)
219
+ │ ├── demo_langgraph_tool_use.py # Minimal quickstart
220
+ │ └── demo.py # Animated demo (internal skill system)
221
+
222
+ ├── tests/ # Test suite
223
+ └── skills/ # Built-in skill definitions (SKILL.md)
224
+ ```
225
+
226
+ ## Further Reading
227
+
228
+ - Blog post: [From Prompt Tweaks to Learning Machines: The Agent Skill Primitive](https://medium.com/@xiweizhou/from-prompt-tweaks-to-learning-machines-the-agent-skill-primitive-93c8fa9dec8c?sk=ac888430da699bce7b635456ae2b1166)
229
+
230
+ ## License
231
+
232
+ Licensed under [BSL 1.1](LICENSE). Free to use in production, but you may not offer CannyForge as a competing hosted service. Converts to Apache 2.0 on 2030-03-01. See LICENSE for full terms.
233
+
234
+ For commercial licensing inquiries: cannyforge@gmail.com
235
+
236
+ ---
237
+
238
+ **CannyForge** — Your agent makes fewer repeated mistakes over time, with measurable evidence.
@@ -48,8 +48,10 @@ from cannyforge.learning import (
48
48
  ErrorRepository,
49
49
  )
50
50
  from cannyforge.tools import ToolDefinition, ToolExecutor, ToolRegistry
51
+ from cannyforge.adapters.langgraph import CannyForgeMiddleware
52
+ from cannyforge.corrections import Correction, CorrectionGenerator
51
53
 
52
- __version__ = "0.2.0"
54
+ __version__ = "0.3.0"
53
55
 
54
56
  __all__ = [
55
57
  # Core
@@ -91,4 +93,9 @@ __all__ = [
91
93
  "ToolDefinition",
92
94
  "ToolExecutor",
93
95
  "ToolRegistry",
96
+ # Adapters
97
+ "CannyForgeMiddleware",
98
+ # Corrections
99
+ "Correction",
100
+ "CorrectionGenerator",
94
101
  ]
@@ -6,5 +6,6 @@ AI/agent frameworks. Each adapter is ~50-80 lines.
6
6
 
7
7
  Available adapters:
8
8
  - langchain: CannyForgeTool for LangChain
9
+ - langgraph: CannyForgeMiddleware for LangGraph agents
9
10
  - crewai: CannyForgeCrewTool for CrewAI
10
11
  """