agentx-dev 3.1.5__tar.gz → 3.2.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 (74) hide show
  1. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/CHANGELOG.md +181 -0
  2. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/CONTRIBUTING.md +105 -105
  3. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/PKG-INFO +7 -7
  4. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/README.md +3 -3
  5. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/DefaultTools.py +2026 -1978
  6. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Embeddings.py +35 -3
  7. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Runner/AgentRun.py +346 -22
  8. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Runner/AsyncAgentRun.py +121 -8
  9. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Supervisor.py +41 -6
  10. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/VectorStores/qdrant_store.py +239 -198
  11. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/WebTools.py +501 -360
  12. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev.egg-info/PKG-INFO +7 -7
  13. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev.egg-info/SOURCES.txt +2 -2
  14. agentx_dev-3.2.0/agentx_dev.egg-info/top_level.txt +3 -0
  15. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/README.md +35 -2
  16. agentx_dev-3.2.0/examples/mcp_github_triage_demo.py +248 -0
  17. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/supervisor_example.py +6 -6
  18. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/pyproject.toml +4 -4
  19. agentx_dev-3.1.5/agentx_dev.egg-info/top_level.txt +0 -14
  20. agentx_dev-3.1.5/host/build_data.py +0 -129
  21. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/AGENTX.md +0 -0
  22. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/LICENSE +0 -0
  23. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/MANIFEST.in +0 -0
  24. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Agents/Agent.py +0 -0
  25. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Agents/__init__.py +0 -0
  26. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/AsyncTools.py +0 -0
  27. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/AutoSetup.py +0 -0
  28. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Cache.py +0 -0
  29. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/ChatModel.py +0 -0
  30. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Compiler.py +0 -0
  31. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Config.py +0 -0
  32. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Evals.py +0 -0
  33. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Handoffs.py +0 -0
  34. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Loader.py +0 -0
  35. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/MCP.py +0 -0
  36. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Memory.py +0 -0
  37. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Observability.py +0 -0
  38. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Planner.py +0 -0
  39. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Runner/__init__.py +0 -0
  40. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Runner/promptTemplate.yaml +0 -0
  41. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Session.py +0 -0
  42. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Splitters.py +0 -0
  43. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Streaming.py +0 -0
  44. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/Tools.py +0 -0
  45. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/VectorStores/__init__.py +0 -0
  46. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/VectorStores/chroma_store.py +0 -0
  47. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/VectorStores/pg_store.py +0 -0
  48. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/__init__.py +0 -0
  49. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/resources/__init__.py +0 -0
  50. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev/resources/promptTemplate.yaml +0 -0
  51. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev.egg-info/dependency_links.txt +0 -0
  52. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/agentx_dev.egg-info/requires.txt +0 -0
  53. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/agentic_rag_demo.py +0 -0
  54. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/async_example.py +0 -0
  55. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/async_quickstart.py +0 -0
  56. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/auto_features_example.py +0 -0
  57. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/caching_example.py +0 -0
  58. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/chatbot_example.py +0 -0
  59. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/complete_example.py +0 -0
  60. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/concurrent_example.py +0 -0
  61. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/concurrent_tool_example.py +0 -0
  62. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/file_agent_demo.py +0 -0
  63. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/function_calling_demo.py +0 -0
  64. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/mcp_demo.py +0 -0
  65. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/observability_example.py +0 -0
  66. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/orchestration_demo.py +0 -0
  67. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/planner_example.py +0 -0
  68. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/robust_link_scraper.py +0 -0
  69. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/supervisor_codebase_analysis_demo.py +0 -0
  70. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/sync_quickstart.py +0 -0
  71. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/v3_1_1_features_demo.py +0 -0
  72. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/v3_1_comprehensive_demo.py +0 -0
  73. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/examples/v3_1_features_demo.py +0 -0
  74. {agentx_dev-3.1.5 → agentx_dev-3.2.0}/setup.cfg +0 -0
@@ -4,6 +4,187 @@ All notable changes to `agentx-dev` are documented here. Format loosely
4
4
  follows [Keep a Changelog](https://keepachangelog.com/); versioning is
5
5
  [Semver](https://semver.org/).
6
6
 
7
+ ## [3.2.0] - 2026-08-13
8
+
9
+ Typed multi-agent pipelines. Specialists can now declare a Pydantic
10
+ output schema once and pass validated instances to each other through
11
+ the Supervisor, instead of downstream agents re-parsing prose.
12
+
13
+ ### Added
14
+
15
+ - **`output_schema` on the `AgentRunner` / `AsyncAgentRunner`
16
+ constructor.** Declare the runner's output shape once
17
+ (`AgentRunner(..., output_schema=QueryIntent)`) instead of passing it
18
+ on every call or describing JSON in the prompt. A per-call
19
+ `output_schema=` still wins when both are set. `None` keeps the exact
20
+ pre-3.2 behaviour: no coercion, `completion.output` stays `None`.
21
+
22
+ - **Schema coercion via forced native function calling.** When a schema
23
+ is in play, the final answer is converted by forcing a provider-native
24
+ tool call against the schema (constrained decoding), not by regexing
25
+ JSON out of prose. The ReAct loop itself is untouched: tool selection
26
+ and intermediate reasoning run exactly as before, and the coercion
27
+ happens once, after the loop finishes. Models without a
28
+ `call_with_tools` implementation fall back to the previous text-JSON
29
+ parsing, so custom `BaseChatModel` subclasses keep working.
30
+ `completion.content` keeps the human-readable answer alongside
31
+ `completion.output` in every case.
32
+
33
+ - **`SubtaskResult.output`.** The Supervisor now preserves each
34
+ specialist's validated Pydantic instance next to its `content` text.
35
+ Consumers that only read `content` are unaffected.
36
+
37
+ - **Structured specialist-to-specialist handoff.** When an earlier step
38
+ produced typed output, `_build_augmented_query` serializes it into the
39
+ next specialist's context as a labelled JSON block
40
+ (`STRUCTURED OUTPUT (QueryIntent): {...}`) followed by the summary
41
+ text, so downstream steps parse fields rather than interpreting
42
+ sentences like `INTENT: ... SEARCH_QUERY: ...`.
43
+
44
+ - **`vector_search_tool` pipeline options.** New kwargs:
45
+ `max_text_chars` (default 500; pass `0` for full untruncated passages,
46
+ which a reranker judging evidence actually needs) and
47
+ `structured_output` (default False; when True the tool returns a JSON
48
+ array of `{id, text, vector_score, metadata}` instead of the
49
+ human-formatted list). Defaults preserve existing behaviour byte-for-
50
+ byte.
51
+
52
+ ### Fixed
53
+
54
+ - **Supervisor planning prompt contradicted the execution engine.** The
55
+ planner rule said sub-agents "do NOT see previous steps' output" and
56
+ discouraged dependency chains, but the dispatcher has threaded prior
57
+ findings into every step since `_build_augmented_query` shipped.
58
+ The rule now tells the planner that sequential steps receive earlier
59
+ results (structured when available) and that chains like
60
+ intent -> retrieval -> reranking are a good plan shape, while still
61
+ requiring same-specialist steps to merge and banning report-only steps.
62
+
63
+ ## [3.1.7] — 2026-07-27
64
+
65
+ ### Changed
66
+
67
+ - **`use_function_calling` default flipped to auto-detect** on
68
+ `AgentRunner` / `AsyncAgentRunner`. The parameter's default type is
69
+ now `Optional[bool] = None`; `None` resolves to `True` when the
70
+ model class overrides `BaseChatModel.call_with_tools` (both `GPT`
71
+ and `Claude` do) and to `False` when it doesn't (or when
72
+ `bind_tools_natively=True`). Callers passing `True`/`False`
73
+ explicitly are unaffected. Rationale: text-mode ReAct requires the
74
+ model to emit strict JSON with any long `action_input` string
75
+ properly escaped — a 1200-word markdown draft with unescaped
76
+ newlines or quotes reliably breaks `json.loads` and killed the run.
77
+ Function-calling mode routes the parser through the SDK's typed
78
+ channel so escaping is handled automatically. The historical
79
+ default (`False`) was the fragile option; the new default matches
80
+ what most users actually want.
81
+
82
+ ### Fixed
83
+
84
+ - **Malformed parser JSON no longer crashes the run.** When the
85
+ text-mode assistant response failed `json.loads` (typically because
86
+ a long `action_input` string had unescaped `"`, `\n`, or backticks),
87
+ the framework used to raise `JSONDecodeError` and unwind the whole
88
+ invocation. The runner now (1) tries a regex-based salvage that
89
+ extracts `{Thought, action, action_input}` from the raw text
90
+ covering the common "outer envelope valid, inner string broke
91
+ escaping" failure, and (2) if salvage fails, feeds a targeted fix
92
+ hint back to the model (`"your last response was not valid JSON;
93
+ emit …, escape newlines as \n"`) and continues the loop bounded
94
+ by `max_iterations`. Exhaustion returns a clear framework message
95
+ rather than an uncaught exception. Applied to both sync and async
96
+ runners via a shared `_salvage_react_json` helper.
97
+ The salvager's action-name regex is intentionally strict
98
+ (`[A-Za-z_][A-Za-z0-9_.\- ]{0,79}`) so it can't hallucinate an
99
+ "action" out of an unrelated `"key":"value"` pair inside malformed
100
+ JSON.
101
+
102
+ - **Verbose trace in `bind_tools_natively` mode now prints tool
103
+ name + args + response.** Previously native runs showed blank
104
+ `[tool.call.start]` / `[tool.call.complete]` pairs (the
105
+ observability layer fires them without the trace context), so you
106
+ couldn't tell which tool the model actually invoked or what came
107
+ back. The runner now prints `[tool] Invoking '<name>' with args:
108
+ <input>` and `[tool] Response: <preview>` (or `[tool] Error: ...`
109
+ when the dispatch raised) in the post-dispatch loop, matching the
110
+ format text-mode and function-calling mode use. Mirrored to the
111
+ async runner.
112
+
113
+ - **`web_fetch_tool(vector_store=...)` auto-ingests fetched pages into
114
+ a vector store** instead of dumping raw HTML into the model's
115
+ context. Fixes the TPM-limit trap: when a research agent fetches
116
+ four articles in parallel (via ``multi_tool_use.parallel`` or
117
+ native binding), the combined bodies can easily exceed 40k tokens
118
+ and blow past a 30k TPM ceiling on the very next model call.
119
+ New parameters on ``web_fetch_tool``:
120
+
121
+ | Kwarg | Default | Effect |
122
+ |---|---|---|
123
+ | ``vector_store`` | ``None`` | When set, each fetch is HTML-stripped, chunked with ``TextSplitter``, embedded via the store's embeddings, and added with ``{src: url, chunk_index, total_chunks}`` metadata. The tool response becomes a compact summary (URL, byte count, chunk count, 240-char preview) — NOT the raw body. The model then calls ``vector_search`` / ``Rag`` to pull only the passages it needs. |
124
+ | ``chunk_size`` | ``1500`` | Characters per chunk when ``vector_store`` is set. Ignored otherwise. |
125
+ | ``chunk_overlap`` | ``200`` | Overlap between adjacent chunks so a fact spanning a boundary is still retrievable. Ignored otherwise. |
126
+
127
+ Backwards-compatible: the positional ``cache_dir`` signature keeps
128
+ working; `web_fetch_tool()` with no ``vector_store`` returns raw
129
+ body as before. Ingest and cache_dir compose — enable both and get
130
+ disk-cached full bodies AND searchable chunks. HTML stripping is
131
+ minimal and dependency-free (regex-based: script/style blocks
132
+ dropped whole, then tags stripped, whitespace collapsed) so the
133
+ ingest path adds no new install dependency. On JSON/plain-text
134
+ responses the stripper is a near no-op.
135
+
136
+ The observation returned to the model shows topical coverage --
137
+ first, middle, and last chunk previews (up to 3 samples,
138
+ deduplicated for short pages) -- so the model can tell what
139
+ topics the page actually covers, not just the intro paragraph.
140
+ Without this the model would only see the page's opening and
141
+ wouldn't know to query for topics discussed later in the same
142
+ page. Explicit instruction in the observation ("query with
143
+ SPECIFIC keywords from the topics above; do NOT re-fetch; do
144
+ NOT ask for the full body") steers the model toward the RAG path
145
+ on follow-up turns.
146
+
147
+ - **`multi_tool_use.parallel` now reaches its dispatch path.**
148
+ When GPT wanted to batch several tool calls into one turn (fetch N
149
+ URLs concurrently, run M searches at once), it emitted OpenAI's
150
+ synthetic `multi_tool_use.parallel` meta-tool. The registry's
151
+ `_dispatch_multi_parallel` / `_adispatch_multi_parallel` handlers
152
+ already knew how to unpack it, but the runner loop's known-tools
153
+ guardrail rejected the name FIRST as unregistered — dumping the
154
+ raw `{"tool_uses": [...]}` payload into the user-facing "final
155
+ answer" and never invoking any of the nested calls. Added
156
+ `multi_tool_use.parallel` to the recognized action set in both
157
+ sync and async runners so the meta-tool flows through to dispatch
158
+ and the existing unpackers run. Nested calls with the `functions.`
159
+ prefix are normalized before dispatch (same as top-level FC
160
+ calls), so the model can emit either shape.
161
+
162
+ - **`Permissions.full_access` / `read_only` auto-wrap a bare string.**
163
+ Passing `full_access("./workspace")` used to iterate the string
164
+ into 11 single-character "subtrees" (Python's `list("./workspace")`)
165
+ — every path check silently rejected because no real path could
166
+ ever match a `"."` or `"/"` "allowed subtree". The classmethod
167
+ now detects a bare string and treats it as `[allowed_paths]`, so
168
+ `full_access("./workspace")` does the intuitive thing (equivalent
169
+ to `full_access(["./workspace"])` and auto-infers the workspace).
170
+ Same fix on `read_only`. List inputs are unchanged.
171
+
172
+ - **`Permissions.full_access` now accepts (and auto-infers)
173
+ `workspace`.** The classmethod set `allowed_paths` but not
174
+ `workspace`, so short paths like `write_file(path="report.md")`
175
+ resolved to CWD (outside the sandbox) and raised
176
+ `PermissionError: access denied` — a landmine that every caller of
177
+ `Permissions.full_access(["./workspace"])` hit sooner or later.
178
+ New signature: `full_access(allowed_paths, *, workspace=None)`.
179
+ When `workspace` isn't passed AND `allowed_paths` has exactly one
180
+ entry, that path is auto-set as the workspace (the "project-scoped
181
+ agent whose one allowed subtree IS its workspace" case, which is
182
+ 99% of use). Two or more paths stay ambiguous and require an
183
+ explicit `workspace=` if short-path resolution is wanted. Pass an
184
+ explicit `workspace=` string to override the auto-choice.
185
+ Backwards-compatible on the positional signature; adds a keyword
186
+ argument that existing callers didn't use.
187
+
7
188
  ## [3.1.5] — 2026-07-26
8
189
 
9
190
  ### Fixed
@@ -1,105 +1,105 @@
1
- # Contributing to agentx-dev
2
-
3
- Thanks for your interest. This is a solo-authored framework, so a few
4
- process choices are opinionated -- they exist to keep the surface area
5
- small and the codebase readable.
6
-
7
- ## Getting set up
8
-
9
- ```bash
10
- git clone https://github.com/shadrach098/Bruce_framework.git
11
- cd Bruce_framework
12
- python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
13
- pip install -e ".[dev,anthropic]"
14
- ```
15
-
16
- Sanity check:
17
-
18
- ```bash
19
- pytest tests/ # should show 127 passing, 3 skipped
20
- python -c "import agentx_dev; print(agentx_dev.__all__)"
21
- ```
22
-
23
- ## Before you open a PR
24
-
25
- 1. **Run the tests.** `pytest tests/ -q` from the repo root.
26
- 2. **Add tests** for whatever you changed. Every existing subsystem
27
- has a `tests/test_<module>.py`; add cases there.
28
- 3. **Keep the change focused.** One PR per feature or fix. If your
29
- change touches five modules and adds three exports, split it.
30
- 4. **Preserve existing behavior** unless the change is explicitly a
31
- breaking one. Backwards-compat is a real value.
32
- 5. **Update docs** if you added or changed a public API. `docs/`
33
- holds the source; run `python host/build_data.py` to regenerate
34
- the browsable site's `data.js`.
35
-
36
- ## Commit + PR style
37
-
38
- - **Commit messages:** `<type>: <short summary>` where type is one of
39
- `feat` / `fix` / `docs` / `test` / `refactor` / `chore`. Follow
40
- with a blank line and the body if the summary isn't enough. Look
41
- at recent commits (`git log --oneline -20`) for the shape.
42
- - **PR titles:** same shape as the commit message. If the PR has
43
- multiple commits, the title summarizes the whole PR.
44
- - **PR descriptions:** what changed, why, and one before/after
45
- example if the change is user-visible.
46
-
47
- ## What lands and what doesn't
48
-
49
- Things that land easily:
50
-
51
- - Bug fixes with a regression test.
52
- - New tools that follow the existing patterns.
53
- - Docs improvements (more examples, clearer explanations, fixing typos).
54
- - New vector-store adapters or provider adapters that follow the
55
- existing interface.
56
- - Test coverage for uncovered paths.
57
-
58
- Things that need discussion first (open an issue):
59
-
60
- - New public classes or modules.
61
- - Changes to public method signatures.
62
- - Anything that grows the dependency footprint of the base install.
63
- - Anything that reshapes the runner loop, `Supervisor`, or
64
- `HandoffCoordinator`.
65
-
66
- Things that don't land:
67
-
68
- - Style-only refactors that reshape existing files.
69
- - Adding a "generic" abstraction over one specific thing.
70
- - Wrapping existing SDKs "for consistency."
71
- - LangChain-compatibility shims.
72
- - Auto-generated boilerplate.
73
-
74
- ## Code style
75
-
76
- - **Docstrings are the source of truth.** Every public class + method
77
- gets one. Say *why* the choice was made, not just what it does.
78
- - **No trailing summary comments** at the end of functions.
79
- - **Type hints on public APIs.** Not needed on internal helpers if
80
- the shape is obvious from three lines up.
81
- - **Small files > large files**, but one-module features > splitting
82
- a single concept across three files for tidiness.
83
-
84
- ## Security-sensitive changes
85
-
86
- The framework has explicit security surfaces:
87
-
88
- - `Permissions` + sandbox enforcement in `DefaultTools.py`
89
- - `run_python` HMAC-signed persistent state in `AutoSetup.py`
90
- - SSRF guard in `WebTools.py`
91
- - Session-id sanitizer in `DefaultTools.py`
92
-
93
- If your change touches any of these, please:
94
-
95
- 1. Add a test that exercises the security check.
96
- 2. Add a note in the PR describing the threat model you considered.
97
-
98
- See `AGENTX.md` at the repo root for the guardrails the framework
99
- imposes on itself.
100
-
101
- ## Questions?
102
-
103
- Open an issue with the "question" label. Solo maintainer, so response
104
- time varies -- a good repro / minimal example is the single biggest
105
- help.
1
+ # Contributing to agentx-dev
2
+
3
+ Thanks for your interest. This is a solo-authored framework, so a few
4
+ process choices are opinionated -- they exist to keep the surface area
5
+ small and the codebase readable.
6
+
7
+ ## Getting set up
8
+
9
+ ```bash
10
+ git clone https://github.com/shadrach098/agentx_dev.git
11
+ cd agentx_dev
12
+ python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
13
+ pip install -e ".[dev,anthropic]"
14
+ ```
15
+
16
+ Sanity check:
17
+
18
+ ```bash
19
+ pytest tests/ # should show 127 passing, 3 skipped
20
+ python -c "import agentx_dev; print(agentx_dev.__all__)"
21
+ ```
22
+
23
+ ## Before you open a PR
24
+
25
+ 1. **Run the tests.** `pytest tests/ -q` from the repo root.
26
+ 2. **Add tests** for whatever you changed. Every existing subsystem
27
+ has a `tests/test_<module>.py`; add cases there.
28
+ 3. **Keep the change focused.** One PR per feature or fix. If your
29
+ change touches five modules and adds three exports, split it.
30
+ 4. **Preserve existing behavior** unless the change is explicitly a
31
+ breaking one. Backwards-compat is a real value.
32
+ 5. **Update docs** if you added or changed a public API. `docs/`
33
+ holds the source; run `python host/build_data.py` to regenerate
34
+ the browsable site's `data.js`.
35
+
36
+ ## Commit + PR style
37
+
38
+ - **Commit messages:** `<type>: <short summary>` where type is one of
39
+ `feat` / `fix` / `docs` / `test` / `refactor` / `chore`. Follow
40
+ with a blank line and the body if the summary isn't enough. Look
41
+ at recent commits (`git log --oneline -20`) for the shape.
42
+ - **PR titles:** same shape as the commit message. If the PR has
43
+ multiple commits, the title summarizes the whole PR.
44
+ - **PR descriptions:** what changed, why, and one before/after
45
+ example if the change is user-visible.
46
+
47
+ ## What lands and what doesn't
48
+
49
+ Things that land easily:
50
+
51
+ - Bug fixes with a regression test.
52
+ - New tools that follow the existing patterns.
53
+ - Docs improvements (more examples, clearer explanations, fixing typos).
54
+ - New vector-store adapters or provider adapters that follow the
55
+ existing interface.
56
+ - Test coverage for uncovered paths.
57
+
58
+ Things that need discussion first (open an issue):
59
+
60
+ - New public classes or modules.
61
+ - Changes to public method signatures.
62
+ - Anything that grows the dependency footprint of the base install.
63
+ - Anything that reshapes the runner loop, `Supervisor`, or
64
+ `HandoffCoordinator`.
65
+
66
+ Things that don't land:
67
+
68
+ - Style-only refactors that reshape existing files.
69
+ - Adding a "generic" abstraction over one specific thing.
70
+ - Wrapping existing SDKs "for consistency."
71
+ - LangChain-compatibility shims.
72
+ - Auto-generated boilerplate.
73
+
74
+ ## Code style
75
+
76
+ - **Docstrings are the source of truth.** Every public class + method
77
+ gets one. Say *why* the choice was made, not just what it does.
78
+ - **No trailing summary comments** at the end of functions.
79
+ - **Type hints on public APIs.** Not needed on internal helpers if
80
+ the shape is obvious from three lines up.
81
+ - **Small files > large files**, but one-module features > splitting
82
+ a single concept across three files for tidiness.
83
+
84
+ ## Security-sensitive changes
85
+
86
+ The framework has explicit security surfaces:
87
+
88
+ - `Permissions` + sandbox enforcement in `DefaultTools.py`
89
+ - `run_python` HMAC-signed persistent state in `AutoSetup.py`
90
+ - SSRF guard in `WebTools.py`
91
+ - Session-id sanitizer in `DefaultTools.py`
92
+
93
+ If your change touches any of these, please:
94
+
95
+ 1. Add a test that exercises the security check.
96
+ 2. Add a note in the PR describing the threat model you considered.
97
+
98
+ See `AGENTX.md` at the repo root for the guardrails the framework
99
+ imposes on itself.
100
+
101
+ ## Questions?
102
+
103
+ Open an issue with the "question" label. Solo maintainer, so response
104
+ time varies -- a good repro / minimal example is the single biggest
105
+ help.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-dev
3
- Version: 3.1.5
3
+ Version: 3.2.0
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
@@ -25,9 +25,9 @@ License: MIT License
25
25
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
26
  SOFTWARE.
27
27
 
28
- Project-URL: Homepage, https://github.com/shadrach098/Bruce_framework
29
- Project-URL: Bug Tracker, https://github.com/shadrach098/Bruce_framework/issues
30
- Project-URL: Source, https://github.com/shadrach098/Bruce_framework
28
+ Project-URL: Homepage, https://github.com/shadrach098/agentx_dev
29
+ Project-URL: Bug Tracker, https://github.com/shadrach098/agentx_dev/issues
30
+ Project-URL: Source, https://github.com/shadrach098/agentx_dev
31
31
  Requires-Python: >=3.10
32
32
  Description-Content-Type: text/markdown
33
33
  License-File: LICENSE
@@ -479,7 +479,7 @@ project with **deny-all** defaults:
479
479
  ```json
480
480
  {
481
481
  "_comment": "Edit this file to control which capabilities the agent has...",
482
- "_docs": "https://github.com/shadrach098/Bruce_framework",
482
+ "_docs": "https://github.com/shadrach098/agentx_dev",
483
483
  "read_files": false,
484
484
  "list_directories": false,
485
485
  "write_files": false,
@@ -1123,5 +1123,5 @@ print(f"Spent: ${llm.usage.estimate_cost(0.003, 0.015):.4f}")
1123
1123
 
1124
1124
  ## Links
1125
1125
 
1126
- - Repo: https://github.com/shadrach098/Bruce_framework
1127
- - Issues: https://github.com/shadrach098/Bruce_framework/issues
1126
+ - Repo: https://github.com/shadrach098/agentx_dev
1127
+ - Issues: https://github.com/shadrach098/agentx_dev/issues
@@ -415,7 +415,7 @@ project with **deny-all** defaults:
415
415
  ```json
416
416
  {
417
417
  "_comment": "Edit this file to control which capabilities the agent has...",
418
- "_docs": "https://github.com/shadrach098/Bruce_framework",
418
+ "_docs": "https://github.com/shadrach098/agentx_dev",
419
419
  "read_files": false,
420
420
  "list_directories": false,
421
421
  "write_files": false,
@@ -1059,5 +1059,5 @@ print(f"Spent: ${llm.usage.estimate_cost(0.003, 0.015):.4f}")
1059
1059
 
1060
1060
  ## Links
1061
1061
 
1062
- - Repo: https://github.com/shadrach098/Bruce_framework
1063
- - Issues: https://github.com/shadrach098/Bruce_framework/issues
1062
+ - Repo: https://github.com/shadrach098/agentx_dev
1063
+ - Issues: https://github.com/shadrach098/agentx_dev/issues