agentx-dev 3.1.4__tar.gz → 3.1.5__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 (73) hide show
  1. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/CHANGELOG.md +317 -209
  2. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/PKG-INFO +15 -1
  3. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/README.md +1063 -1049
  4. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/ChatModel.py +58 -5
  5. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Runner/AgentRun.py +2359 -2149
  6. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Runner/AsyncAgentRun.py +895 -787
  7. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Supervisor.py +262 -30
  8. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev.egg-info/PKG-INFO +15 -1
  9. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev.egg-info/SOURCES.txt +3 -1
  10. agentx_dev-3.1.5/agentx_dev.egg-info/top_level.txt +14 -0
  11. agentx_dev-3.1.5/examples/robust_link_scraper.py +214 -0
  12. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/supervisor_example.py +6 -5
  13. agentx_dev-3.1.5/host/build_data.py +129 -0
  14. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/pyproject.toml +1 -1
  15. agentx_dev-3.1.4/agentx_dev.egg-info/top_level.txt +0 -3
  16. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/AGENTX.md +0 -0
  17. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/CONTRIBUTING.md +0 -0
  18. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/LICENSE +0 -0
  19. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/MANIFEST.in +0 -0
  20. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Agents/Agent.py +0 -0
  21. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Agents/__init__.py +0 -0
  22. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/AsyncTools.py +0 -0
  23. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/AutoSetup.py +0 -0
  24. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Cache.py +0 -0
  25. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Compiler.py +0 -0
  26. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Config.py +0 -0
  27. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/DefaultTools.py +0 -0
  28. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Embeddings.py +0 -0
  29. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Evals.py +0 -0
  30. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Handoffs.py +0 -0
  31. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Loader.py +0 -0
  32. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/MCP.py +0 -0
  33. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Memory.py +0 -0
  34. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Observability.py +0 -0
  35. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Planner.py +0 -0
  36. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Runner/__init__.py +0 -0
  37. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Runner/promptTemplate.yaml +0 -0
  38. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Session.py +0 -0
  39. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Splitters.py +0 -0
  40. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Streaming.py +0 -0
  41. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/Tools.py +0 -0
  42. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/VectorStores/__init__.py +0 -0
  43. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/VectorStores/chroma_store.py +0 -0
  44. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/VectorStores/pg_store.py +0 -0
  45. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/VectorStores/qdrant_store.py +0 -0
  46. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/WebTools.py +0 -0
  47. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/__init__.py +0 -0
  48. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/resources/__init__.py +0 -0
  49. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev/resources/promptTemplate.yaml +0 -0
  50. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev.egg-info/dependency_links.txt +0 -0
  51. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/agentx_dev.egg-info/requires.txt +0 -0
  52. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/README.md +0 -0
  53. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/agentic_rag_demo.py +0 -0
  54. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/async_example.py +0 -0
  55. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/async_quickstart.py +0 -0
  56. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/auto_features_example.py +0 -0
  57. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/caching_example.py +0 -0
  58. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/chatbot_example.py +0 -0
  59. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/complete_example.py +0 -0
  60. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/concurrent_example.py +0 -0
  61. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/concurrent_tool_example.py +0 -0
  62. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/file_agent_demo.py +0 -0
  63. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/function_calling_demo.py +0 -0
  64. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/mcp_demo.py +0 -0
  65. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/observability_example.py +0 -0
  66. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/orchestration_demo.py +0 -0
  67. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/planner_example.py +0 -0
  68. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/supervisor_codebase_analysis_demo.py +0 -0
  69. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/sync_quickstart.py +0 -0
  70. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/v3_1_1_features_demo.py +0 -0
  71. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/v3_1_comprehensive_demo.py +0 -0
  72. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/examples/v3_1_features_demo.py +0 -0
  73. {agentx_dev-3.1.4 → agentx_dev-3.1.5}/setup.cfg +0 -0
@@ -1,209 +1,317 @@
1
- # Changelog
2
-
3
- All notable changes to `agentx-dev` are documented here. Format loosely
4
- follows [Keep a Changelog](https://keepachangelog.com/); versioning is
5
- [Semver](https://semver.org/).
6
-
7
- ## [3.1.3] — 2026-07-22
8
-
9
- Docs-only patch. No code changes since 3.1.2. Users on 3.1.2 don't
10
- need to upgrade for functionality; upgrade to pick up the improved
11
- onboarding docs bundled in the sdist.
12
-
13
- ### Documentation
14
-
15
- - **Tools doc rewritten to answer "how do I actually use these?"**
16
- Added §0 `How each built-in tool is registered` as the entry
17
- section. Two registration paths — auto vs manual — laid out in a
18
- table on the first screen. Six runnable subsections covering every
19
- combination:
20
- - §0.1 DefaultTools via `Permissions(...)` (auto)
21
- - §0.2 WebTools via `tools=[web_search_tool(), web_fetch_tool()]`
22
- - §0.3 RAG via `TextSplitter` -> `VectorStore.add_documents` ->
23
- `vector_search_tool(store)`
24
- - §0.4 Handoffs via `handoff_tool` + `HandoffCoordinator`
25
- - §0.5 Custom `StructuredTool` from scratch
26
- - §0.6 Fully-loaded runner combining all of the above
27
- - §0.7 Rules on name collisions, invisible-denied-capabilities,
28
- async-tool behavior
29
- The existing inventory + wrapper / controls / cheat-sheet sections
30
- are unchanged; they now sit after the "how to use them" primer
31
- instead of before it.
32
-
33
- ## [3.1.2] — 2026-07-22
34
-
35
- Patch release. Two independent fixes.
36
-
37
- ### Fixed
38
-
39
- - **`llm_judge` correctly parses YES/NO across providers.** The judge
40
- parser was comparing the reply's first word to the literal string
41
- `"YES"`. GPT-4o answers `"YES,"` (comma-suffixed), which failed the
42
- equality check and marked every genuine PASS as FAIL. Claude replies
43
- `"YES"` without punctuation so the bug hid during local development.
44
- Fixed by matching `\b(YES|NO)\b` (word-boundary regex, case-
45
- insensitive) at the start of the reply. Handles every real shape:
46
- `YES`, `YES.`, `YES!`, `YES, exactly right`, `Yes.`, `yes -- reason`.
47
- Ambiguous replies (`Maybe`, empty string) still fail closed.
48
- - Regression test `test_llm_judge_parses_various_verdict_shapes`
49
- covers 8 YES shapes, 5 NO shapes, and 4 ambiguous replies.
50
-
51
- ### Added
52
-
53
- - **`agentx_dev.Tools` is a one-stop tools namespace.** Users no
54
- longer need to remember which module each tool lives in:
55
-
56
- ```python
57
- from agentx_dev.Tools import (
58
- StandardTool, StructuredTool,
59
- AsyncStandardTool, AsyncStructuredTool,
60
- web_search_tool, web_fetch_tool,
61
- vector_search_tool, handoff_tool,
62
- DefaultTools, Permissions,
63
- )
64
- ```
65
-
66
- Both this form and the pre-existing `from agentx_dev import X`
67
- form coexist. Implementation uses PEP 562 module `__getattr__`
68
- and `__dir__` so re-exports are lazy (no import cost for modules
69
- the caller doesn't touch) and show up in IDE autocomplete +
70
- `dir(agentx_dev.Tools)`.
71
-
72
- ## [3.1.1] — 2026-07-21
73
-
74
- Second batch of 3.1 features + a full docs + brand pass.
75
-
76
- ### Added
77
-
78
- **Streaming through orchestration**
79
- - `Supervisor.stream()` / `AsyncSupervisor.astream()` emit
80
- `plan_start` / `plan` / `dispatch` / `subtask_result` /
81
- `synthesize_start` / `final` / `completion` events.
82
- - `HandoffCoordinator.stream()` / `.astream()` emit `invoke` /
83
- `completion` / `handoff` / `final` / `result` events per hop.
84
- - Legacy `.run()` / `.arun()` refactored to consume the streams (no
85
- code duplication).
86
-
87
- **Prompt optimization — `Compiled`**
88
- - New `agentx_dev.Compiler` module.
89
- - `Compiled(runner_factory, trainset, ...)` iteratively refines a
90
- runner's `system_addendum` against the eval harness. Half of
91
- DSPy's power at a tenth of the surface.
92
-
93
- **Anthropic Batch API**
94
- - `Claude.batch(requests)` submits many prompts at Anthropic's 50%-off
95
- batch rate, polls to completion, returns results in submission order.
96
- - Per-request error dicts on failure; token usage funneled into
97
- `TokenUsage` so cost tracking stays a single source of truth.
98
-
99
- **Vector store adapters — `agentx_dev.VectorStores`**
100
- - `ChromaVectorStore`, `QdrantVectorStore`, `PgVectorStore` — same
101
- public shape as the in-memory `VectorStore` (`add` / `search` /
102
- `delete` / `clear` / `__len__` / `embeddings`).
103
- - `vector_search_tool()` and `SemanticMemory` accept any of them.
104
- - SDK imports lazy; friendly `ImportError` when the underlying SDK
105
- is missing.
106
-
107
- **Trace viewer (`viewer/`)**
108
- - Self-hosted single-page app that reads `FileHook` JSONL and renders
109
- a timeline with type/text filters, summary sidebar, JSON drill-down.
110
- - Works from `file://`, no server required.
111
-
112
- **Docs site (`host/`)**
113
- - Full editorial dark-first design system (JetBrains Mono headings,
114
- Inter body, `#B8FF3E` electric-lime accent).
115
- - Command palette (`Cmd+K`) with keyboard navigation and live search.
116
- - Hero code snippet with hand-tinted syntax highlighting.
117
- - Reading progress bar, breadcrumbs, header anchor links.
118
- - Sidebar sliding active marker, collapsible groups.
119
- - Code copy buttons, language labels.
120
- - Right-rail auto-TOC with `IntersectionObserver` scrollspy.
121
- - Dark/light theme toggle, persisted.
122
- - Cache-busted assets so edits land on refresh without hard-reload.
123
-
124
- **Brand identity (`brand/`)**
125
- - Full brand kit: 5 SVG assets (`mark`, `mono`, `wordmark`, `logo-full`,
126
- `app-icon`), `BRAND.md` strategy doc, rendered brand-kit HTML deck.
127
- - Copy audit dropped "small" (weak) and "LangChain" references from
128
- all marketing surfaces.
129
- - Favicon wired into docs + trace viewer.
130
-
131
- **Test suite (`tests/`)**
132
- - Restored + expanded pytest suite: 127 tests passing (3 skipped for
133
- absent optional SDKs).
134
- - Coverage: parser + all `AgentType` variants, `ToolRegistry`
135
- (dispatch / dup-guard / circuit-breaker / timeout), Permissions
136
- (capability gating + sandbox + traversal), budgets (cost / rate /
137
- retry / non-retryable HTTP), runner loop (streaming + output_schema
138
- + chat history), embeddings + `VectorStore` + `SemanticMemory`,
139
- handoffs (bounded hops + history sanitization), evals harness
140
- (all assertion helpers + JSON case loaders), vector-store adapter
141
- shape conformance.
142
-
143
- **Docs (`docs/`)**
144
- - Full docs tree (34 pages), including new pages for:
145
- vector store adapters, prompt optimization, batch API, trace viewer,
146
- and a **use-cases** landing (13 concrete scenarios with runnable code).
147
- - Rewrote **Tools** page to enumerate every built-in tool with args,
148
- return shape, capability flag, and use-case guidance.
149
- - Rewrote **Agents** page to cover all four orchestration
150
- architectures (Solo / Supervisor / Handoffs / Compiled) with
151
- decision trees, worked examples, and cheat sheet.
152
- - **Agentic RAG chatbot** as use case §13 — multi-query decomposition,
153
- parallel retrieval, self-critique, citations, user memory.
154
-
155
- **Examples**
156
- - `examples/agentic_rag_demo.py` — the runnable version of the
157
- agentic RAG use case. Auto-seeds a KB if none exists, `--demo` flag
158
- runs a 3-turn scripted session proving user-notes recall works.
159
-
160
- **Package**
161
- - `[chroma]`, `[qdrant]`, `[pgvector]`, `[dev]` extras added.
162
- - `[anthropic]` bumped to `>=0.36` (Batch API + prompt cache).
163
-
164
- ### Fixed
165
-
166
- - `AgentRunner._iter_run` in `bind_tools_natively=True` mode uses a
167
- minimal system prompt instead of the AgentType template so the
168
- ReAct `action/action_input` scaffold no longer fights the native
169
- tool interface. Previously produced JSON-blob answers under GPT.
170
- - `HandoffCoordinator._sanitize_history_for_next_agent` strips tool
171
- and function role messages between hops so tool_call_ids from a
172
- previous agent don't leak into the next model's call (OpenAI 400).
173
- - Docs site marker positioning uses double-`requestAnimationFrame` +
174
- `document.fonts.ready` so the sidebar accent bar lands on the
175
- correct row even on a cold font cache.
176
- - Primary hero CTA color uses `#doc .hero-cta a.primary` selector to
177
- outrank `#doc a` link styling (previously rendered lime-on-lime
178
- and was invisible).
179
-
180
- ### Notes
181
-
182
- - Package version bumped from `3.0.6` to `3.1.1`. The 3.1.0 release
183
- did not ship publicly — 3.1.1 is the first 3.1-tagged PyPI release
184
- and includes both batches of features.
185
-
186
- ## [3.1.0] — internal only (commits 52840e7)
187
-
188
- First batch of 3.1 features. Committed but not released to PyPI.
189
- Merged into 3.1.1 for the public release.
190
-
191
- ### Added
192
- - Anthropic prompt caching (`Claude(enable_prompt_cache=True)`).
193
- - Parallel per-turn tool dispatch in `AgentRunner`
194
- (`bind_tools_natively=True`, `parallel_tool_workers`).
195
- - Semantic memory (`SemanticMemory`, embeddings-backed retrieval).
196
- - RAG core (`Embeddings`, `HashEmbeddings`, `OpenAIEmbeddings`,
197
- `VectorStore`, `VectorHit`, `vector_search_tool()`).
198
- - Agent-to-agent handoffs (`HandoffRequest`, `handoff_tool`,
199
- `HandoffCoordinator`, `HandoffResult`).
200
- - Evals harness (`EvalCase`, `EvalRunner`, `EvalReport`, 7 assertion
201
- helpers, JSON case loader, `python -m agentx_dev.Evals run` CLI).
202
- - `TokenUsage.cache_hit_ratio` property.
203
-
204
- ## [3.0.6] — 2026-03 (baseline)
205
-
206
- Security hardening baseline (SSRF guard on `web_fetch`, HMAC-signed
207
- persistent state, scrubbed subprocess env, path sanitizer,
208
- `permissions.json` mode 0o600, ReDoS guard on `grep`,
209
- `invoke`/`ainvoke` accept bare strings and message lists).
1
+ # Changelog
2
+
3
+ All notable changes to `agentx-dev` are documented here. Format loosely
4
+ follows [Keep a Changelog](https://keepachangelog.com/); versioning is
5
+ [Semver](https://semver.org/).
6
+
7
+ ## [3.1.5] — 2026-07-26
8
+
9
+ ### Fixed
10
+
11
+ - **Text-mode tool results no longer use `role: "function"`.** In text
12
+ mode (the default — no `use_function_calling`) the runner fed each tool
13
+ observation back to the model as a `role: "function"` message. Newer
14
+ OpenAI models reject that role outright (`400 … 'messages[N].role' does
15
+ not support 'function' with this model`, e.g. gpt-5.x), and Anthropic
16
+ never accepted it — text-mode multi-tool runs on Claude were latently
17
+ broken too; older GPT models simply still tolerated the legacy role.
18
+ Tool observations now go back as a plain `role: "user"` turn framed as
19
+ `Observation: …`, which every provider and model generation accepts and
20
+ which matches the ReAct template's own few-shot convention.
21
+ Function-calling mode is unchanged (native `role: "tool"` +
22
+ `tool_call_id`). The async runner was additionally emitting `function`
23
+ unconditionally (even in FC mode); it now uses the same shared helper.
24
+
25
+ ### Added
26
+
27
+ - **`subtask_success_check` on `Supervisor` / `AsyncSupervisor`.** Opt-in
28
+ predicate `(SubtaskResult) -> bool | str` that decides whether a
29
+ *returned* (non-raised) sub-task result is actually acceptable — the
30
+ "ran fine but produced nothing useful" case a plain retry can't catch
31
+ (a scraper that saved 0 links, an extractor that found nothing). Return
32
+ `True` to accept, or `False`/a `str` reason to reject; a rejected
33
+ result is retried like a raised error, with the reason fed back into the
34
+ query, bounded by `max_subtask_retries`. After retries are exhausted the
35
+ last result is returned with its `error` set (content preserved). A
36
+ check that itself raises is treated as "accept" so a buggy predicate
37
+ can't wedge the run. Default `None` keeps the exceptions-only behavior.
38
+ New example `examples/robust_link_scraper.py` wires it together with a
39
+ scraping `system_addendum` (parse relative+absolute hrefs, fall back to
40
+ `sitemap.xml` on JS-rendered sites).
41
+
42
+ ## [3.1.4] — 2026-07-26
43
+
44
+ ### Fixed
45
+
46
+ - **A malformed-JSON tool argument no longer crashes the whole agent
47
+ run.** When a model emitted a Python snippet or a Windows path as a
48
+ tool-call argument — `re.findall(r'\d+')`, `C:\Users` — the `\d` / `\U`
49
+ are illegal JSON escapes, and the OpenAI adapter's eager
50
+ `json.loads(call.function.arguments)` raised `JSONDecodeError` and
51
+ `raise`d it, unwinding the entire ReAct loop before the agent's own
52
+ retry machinery could act. Under a Supervisor this surfaced as a bare
53
+ `ERROR: Invalid \escape: line 1 column 598` and the sub-task was
54
+ abandoned. Now:
55
+ - `_parse_tool_arguments` repairs the common case (backslashes that
56
+ don't begin a valid JSON escape are doubled), recovering `\d`,
57
+ `\w`, `\s`, etc. with zero extra round-trips. A backslash before a
58
+ valid-escape letter (`\b`, `\n`, …) remains ambiguous and is left
59
+ as the escape — a documented limit.
60
+ - When repair fails, `call_with_tools` returns a dedicated
61
+ `invalid_tool_args` result and the loop feeds the error back as a
62
+ retryable observation ("your arguments weren't valid JSON — escape
63
+ backslashes and resend"), bounded by `max_iterations`, in all
64
+ three modes across both `AgentRunner` and `AsyncAgentRunner`.
65
+ `Claude` was already immune (its tool inputs arrive pre-parsed).
66
+
67
+ - **A tool-call preamble is no longer returned as the final answer.**
68
+ Models routinely end a turn with an announcement instead of an action
69
+ — "I'll look up your recent scores to get a clear view of your
70
+ communication skills. Just a second!" — and every "no tool call
71
+ found" branch in both runners was coded as *this text is the answer,
72
+ break*. The loop terminated on iteration 1 and the caller got a
73
+ promise instead of a result. Three sites per runner were affected:
74
+ the native-binding path (`type != "tool_use"`), the
75
+ `use_function_calling` path (parser unresolved), and the JSON-text
76
+ path (response didn't parse). `max_iterations` never helped, because
77
+ the break happened before any iteration was spent.
78
+
79
+ The runner now feeds the model one corrective nudge — "your last turn
80
+ had no action, so nothing happened; do it, don't announce it" — and
81
+ continues the loop. Verified against both `AgentRunner` and
82
+ `AsyncAgentRunner` in all three modes.
83
+
84
+ ### Added
85
+
86
+ - **Proactive "act, don't announce" system-prompt clause.** The reactive
87
+ `text_turn_nudges` fix corrects an agent *after* it narrates instead of
88
+ acting; this clause heads it off. When (and only when) an agent has
89
+ tools, its system prompt now tells it to call the tool rather than
90
+ reply "I'll do X / just a second" and stop — and to report what it DID
91
+ in past tense. Injected in all three modes across both runners; skipped
92
+ for tool-less chat agents, where prose is the correct answer. Sits
93
+ before any `system_addendum` so a caller's role instructions still win.
94
+
95
+ - **`max_subtask_retries` on `Supervisor` / `AsyncSupervisor`** (default
96
+ `1`). A sub-task that raised used to be recorded as an error and the
97
+ Supervisor moved straight to synthesis — no second attempt. Now a
98
+ failed sub-task is re-dispatched up to this many times, with the prior
99
+ error appended to the query so the specialist knows what to fix
100
+ ("your previous attempt failed with X — diagnose and try again").
101
+ Bounded and informed: only raised exceptions trigger a retry (a
102
+ sub-task that returns content is accepted as-is, since the Supervisor
103
+ can't tell "terse but correct" from "wrong"), and the error text is
104
+ fed back rather than blindly re-running. Set to `0` for the old
105
+ quit-on-first-failure behavior. Applies in both sequential and
106
+ concurrent async modes.
107
+
108
+ - **`text_turn_nudges` on `AgentRunner` / `AsyncAgentRunner`** (default
109
+ `1`). Caps the re-prompts described above at one extra LLM call per
110
+ run; after the budget is spent the model's text stands as the answer.
111
+ Set to `0` for the previous behavior. Automatically skipped when no
112
+ tools are registered, since a runner with no tools is a plain chat
113
+ call and prose genuinely is the answer there.
114
+
115
+ ## [3.1.3] — 2026-07-22
116
+
117
+ Docs-only patch. No code changes since 3.1.2. Users on 3.1.2 don't
118
+ need to upgrade for functionality; upgrade to pick up the improved
119
+ onboarding docs bundled in the sdist.
120
+
121
+ ### Documentation
122
+
123
+ - **Tools doc rewritten to answer "how do I actually use these?"**
124
+ Added §0 `How each built-in tool is registered` as the entry
125
+ section. Two registration paths — auto vs manual — laid out in a
126
+ table on the first screen. Six runnable subsections covering every
127
+ combination:
128
+ - §0.1 DefaultTools via `Permissions(...)` (auto)
129
+ - §0.2 WebTools via `tools=[web_search_tool(), web_fetch_tool()]`
130
+ - §0.3 RAG via `TextSplitter` -> `VectorStore.add_documents` ->
131
+ `vector_search_tool(store)`
132
+ - §0.4 Handoffs via `handoff_tool` + `HandoffCoordinator`
133
+ - §0.5 Custom `StructuredTool` from scratch
134
+ - §0.6 Fully-loaded runner combining all of the above
135
+ - §0.7 Rules on name collisions, invisible-denied-capabilities,
136
+ async-tool behavior
137
+ The existing inventory + wrapper / controls / cheat-sheet sections
138
+ are unchanged; they now sit after the "how to use them" primer
139
+ instead of before it.
140
+
141
+ ## [3.1.2] — 2026-07-22
142
+
143
+ Patch release. Two independent fixes.
144
+
145
+ ### Fixed
146
+
147
+ - **`llm_judge` correctly parses YES/NO across providers.** The judge
148
+ parser was comparing the reply's first word to the literal string
149
+ `"YES"`. GPT-4o answers `"YES,"` (comma-suffixed), which failed the
150
+ equality check and marked every genuine PASS as FAIL. Claude replies
151
+ `"YES"` without punctuation so the bug hid during local development.
152
+ Fixed by matching `\b(YES|NO)\b` (word-boundary regex, case-
153
+ insensitive) at the start of the reply. Handles every real shape:
154
+ `YES`, `YES.`, `YES!`, `YES, exactly right`, `Yes.`, `yes -- reason`.
155
+ Ambiguous replies (`Maybe`, empty string) still fail closed.
156
+ - Regression test `test_llm_judge_parses_various_verdict_shapes`
157
+ covers 8 YES shapes, 5 NO shapes, and 4 ambiguous replies.
158
+
159
+ ### Added
160
+
161
+ - **`agentx_dev.Tools` is a one-stop tools namespace.** Users no
162
+ longer need to remember which module each tool lives in:
163
+
164
+ ```python
165
+ from agentx_dev.Tools import (
166
+ StandardTool, StructuredTool,
167
+ AsyncStandardTool, AsyncStructuredTool,
168
+ web_search_tool, web_fetch_tool,
169
+ vector_search_tool, handoff_tool,
170
+ DefaultTools, Permissions,
171
+ )
172
+ ```
173
+
174
+ Both this form and the pre-existing `from agentx_dev import X`
175
+ form coexist. Implementation uses PEP 562 module `__getattr__`
176
+ and `__dir__` so re-exports are lazy (no import cost for modules
177
+ the caller doesn't touch) and show up in IDE autocomplete +
178
+ `dir(agentx_dev.Tools)`.
179
+
180
+ ## [3.1.1] — 2026-07-21
181
+
182
+ Second batch of 3.1 features + a full docs + brand pass.
183
+
184
+ ### Added
185
+
186
+ **Streaming through orchestration**
187
+ - `Supervisor.stream()` / `AsyncSupervisor.astream()` emit
188
+ `plan_start` / `plan` / `dispatch` / `subtask_result` /
189
+ `synthesize_start` / `final` / `completion` events.
190
+ - `HandoffCoordinator.stream()` / `.astream()` emit `invoke` /
191
+ `completion` / `handoff` / `final` / `result` events per hop.
192
+ - Legacy `.run()` / `.arun()` refactored to consume the streams (no
193
+ code duplication).
194
+
195
+ **Prompt optimization — `Compiled`**
196
+ - New `agentx_dev.Compiler` module.
197
+ - `Compiled(runner_factory, trainset, ...)` iteratively refines a
198
+ runner's `system_addendum` against the eval harness. Half of
199
+ DSPy's power at a tenth of the surface.
200
+
201
+ **Anthropic Batch API**
202
+ - `Claude.batch(requests)` submits many prompts at Anthropic's 50%-off
203
+ batch rate, polls to completion, returns results in submission order.
204
+ - Per-request error dicts on failure; token usage funneled into
205
+ `TokenUsage` so cost tracking stays a single source of truth.
206
+
207
+ **Vector store adapters — `agentx_dev.VectorStores`**
208
+ - `ChromaVectorStore`, `QdrantVectorStore`, `PgVectorStore` — same
209
+ public shape as the in-memory `VectorStore` (`add` / `search` /
210
+ `delete` / `clear` / `__len__` / `embeddings`).
211
+ - `vector_search_tool()` and `SemanticMemory` accept any of them.
212
+ - SDK imports lazy; friendly `ImportError` when the underlying SDK
213
+ is missing.
214
+
215
+ **Trace viewer (`viewer/`)**
216
+ - Self-hosted single-page app that reads `FileHook` JSONL and renders
217
+ a timeline with type/text filters, summary sidebar, JSON drill-down.
218
+ - Works from `file://`, no server required.
219
+
220
+ **Docs site (`host/`)**
221
+ - Full editorial dark-first design system (JetBrains Mono headings,
222
+ Inter body, `#B8FF3E` electric-lime accent).
223
+ - Command palette (`Cmd+K`) with keyboard navigation and live search.
224
+ - Hero code snippet with hand-tinted syntax highlighting.
225
+ - Reading progress bar, breadcrumbs, header anchor links.
226
+ - Sidebar sliding active marker, collapsible groups.
227
+ - Code copy buttons, language labels.
228
+ - Right-rail auto-TOC with `IntersectionObserver` scrollspy.
229
+ - Dark/light theme toggle, persisted.
230
+ - Cache-busted assets so edits land on refresh without hard-reload.
231
+
232
+ **Brand identity (`brand/`)**
233
+ - Full brand kit: 5 SVG assets (`mark`, `mono`, `wordmark`, `logo-full`,
234
+ `app-icon`), `BRAND.md` strategy doc, rendered brand-kit HTML deck.
235
+ - Copy audit dropped "small" (weak) and "LangChain" references from
236
+ all marketing surfaces.
237
+ - Favicon wired into docs + trace viewer.
238
+
239
+ **Test suite (`tests/`)**
240
+ - Restored + expanded pytest suite: 127 tests passing (3 skipped for
241
+ absent optional SDKs).
242
+ - Coverage: parser + all `AgentType` variants, `ToolRegistry`
243
+ (dispatch / dup-guard / circuit-breaker / timeout), Permissions
244
+ (capability gating + sandbox + traversal), budgets (cost / rate /
245
+ retry / non-retryable HTTP), runner loop (streaming + output_schema
246
+ + chat history), embeddings + `VectorStore` + `SemanticMemory`,
247
+ handoffs (bounded hops + history sanitization), evals harness
248
+ (all assertion helpers + JSON case loaders), vector-store adapter
249
+ shape conformance.
250
+
251
+ **Docs (`docs/`)**
252
+ - Full docs tree (34 pages), including new pages for:
253
+ vector store adapters, prompt optimization, batch API, trace viewer,
254
+ and a **use-cases** landing (13 concrete scenarios with runnable code).
255
+ - Rewrote **Tools** page to enumerate every built-in tool with args,
256
+ return shape, capability flag, and use-case guidance.
257
+ - Rewrote **Agents** page to cover all four orchestration
258
+ architectures (Solo / Supervisor / Handoffs / Compiled) with
259
+ decision trees, worked examples, and cheat sheet.
260
+ - **Agentic RAG chatbot** as use case §13 — multi-query decomposition,
261
+ parallel retrieval, self-critique, citations, user memory.
262
+
263
+ **Examples**
264
+ - `examples/agentic_rag_demo.py` — the runnable version of the
265
+ agentic RAG use case. Auto-seeds a KB if none exists, `--demo` flag
266
+ runs a 3-turn scripted session proving user-notes recall works.
267
+
268
+ **Package**
269
+ - `[chroma]`, `[qdrant]`, `[pgvector]`, `[dev]` extras added.
270
+ - `[anthropic]` bumped to `>=0.36` (Batch API + prompt cache).
271
+
272
+ ### Fixed
273
+
274
+ - `AgentRunner._iter_run` in `bind_tools_natively=True` mode uses a
275
+ minimal system prompt instead of the AgentType template so the
276
+ ReAct `action/action_input` scaffold no longer fights the native
277
+ tool interface. Previously produced JSON-blob answers under GPT.
278
+ - `HandoffCoordinator._sanitize_history_for_next_agent` strips tool
279
+ and function role messages between hops so tool_call_ids from a
280
+ previous agent don't leak into the next model's call (OpenAI 400).
281
+ - Docs site marker positioning uses double-`requestAnimationFrame` +
282
+ `document.fonts.ready` so the sidebar accent bar lands on the
283
+ correct row even on a cold font cache.
284
+ - Primary hero CTA color uses `#doc .hero-cta a.primary` selector to
285
+ outrank `#doc a` link styling (previously rendered lime-on-lime
286
+ and was invisible).
287
+
288
+ ### Notes
289
+
290
+ - Package version bumped from `3.0.6` to `3.1.1`. The 3.1.0 release
291
+ did not ship publicly — 3.1.1 is the first 3.1-tagged PyPI release
292
+ and includes both batches of features.
293
+
294
+ ## [3.1.0] — internal only (commits 52840e7)
295
+
296
+ First batch of 3.1 features. Committed but not released to PyPI.
297
+ Merged into 3.1.1 for the public release.
298
+
299
+ ### Added
300
+ - Anthropic prompt caching (`Claude(enable_prompt_cache=True)`).
301
+ - Parallel per-turn tool dispatch in `AgentRunner`
302
+ (`bind_tools_natively=True`, `parallel_tool_workers`).
303
+ - Semantic memory (`SemanticMemory`, embeddings-backed retrieval).
304
+ - RAG core (`Embeddings`, `HashEmbeddings`, `OpenAIEmbeddings`,
305
+ `VectorStore`, `VectorHit`, `vector_search_tool()`).
306
+ - Agent-to-agent handoffs (`HandoffRequest`, `handoff_tool`,
307
+ `HandoffCoordinator`, `HandoffResult`).
308
+ - Evals harness (`EvalCase`, `EvalRunner`, `EvalReport`, 7 assertion
309
+ helpers, JSON case loader, `python -m agentx_dev.Evals run` CLI).
310
+ - `TokenUsage.cache_hit_ratio` property.
311
+
312
+ ## [3.0.6] — 2026-03 (baseline)
313
+
314
+ Security hardening baseline (SSRF guard on `web_fetch`, HMAC-signed
315
+ persistent state, scrubbed subprocess env, path sanitizer,
316
+ `permissions.json` mode 0o600, ReDoS guard on `grep`,
317
+ `invoke`/`ainvoke` accept bare strings and message lists).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-dev
3
- Version: 3.1.4
3
+ Version: 3.1.5
4
4
  Summary: A production-grade Python framework for building LLM agents. Multi-provider chat, permission-gated tools, RAG (in-mem + Chroma/Qdrant/pgvector), semantic memory, Supervisor + Handoffs multi-agent orchestration with streaming, evals harness, prompt caching, Batch API, prompt-optimizer, MCP integration.
5
5
  Author-email: Bruce-Arhin Shadrach <brucearhin098@gmail.com>
6
6
  License: MIT License
@@ -73,6 +73,19 @@ you can paste and run.
73
73
 
74
74
  ---
75
75
 
76
+ ## What's new in 3.1.4 — reliability hardening
77
+
78
+ Four fixes for the "the agent said it would do the thing but didn't"
79
+ class of failure. All additive; existing code keeps working, and the new
80
+ recovery defaults are strictly safer.
81
+
82
+ | Fix | What changed |
83
+ |---|---|
84
+ | **Tool-call preamble no longer becomes the answer** | When the model ends a turn with plain text and no tool call (*"I'll look up your scores. Just a second!"*), the runner re-prompts it to act instead of freezing the preamble as the final answer. Bounded by `text_turn_nudges` (default 1; `0` disables). Skipped when no tools are registered — there, prose is the answer. |
85
+ | **Proactive "act, don't announce" clause** | Tool-using agents now get a system-prompt clause telling them to call the tool and report what they DID, rather than narrate what they're about to do. Heads off the preamble at the source. |
86
+ | **Malformed-JSON tool arguments recover instead of crashing** | A code snippet or Windows path in a tool argument (`re.findall(r'\d+')`, `C:\Users`) is invalid JSON. The framework now repairs the common escape mistakes, and otherwise feeds the error back so the model resends — instead of unwinding the whole run (which surfaced under a Supervisor as `ERROR: Invalid \escape`). `Claude()` was already immune. |
87
+ | **Supervisor retries a failed sub-task** | `Supervisor` / `AsyncSupervisor` gained `max_subtask_retries` (default 1). A sub-task that raises is re-dispatched with the prior error appended, instead of quit-on-first-failure. Bounded and informed; set `0` for the old behavior. |
88
+
76
89
  ## What's new in 3.1 — power features
77
90
 
78
91
  Six force-multipliers land in one release. All additive; existing code
@@ -681,6 +694,7 @@ supervisor = Supervisor(
681
694
  "python_agent": ("Python code execution", python_agent),
682
695
  },
683
696
  max_subtasks=5,
697
+ max_subtask_retries=1, # retry a failed sub-task once, error fed back
684
698
  verbose=True, # framework prints plan / dispatch / result / final
685
699
  )
686
700