agentnode-sdk 0.4.0__tar.gz → 0.4.1__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 (55) hide show
  1. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/.env.example +8 -8
  2. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/.gitignore +12 -0
  3. agentnode_sdk-0.4.1/CHANGELOG.md +40 -0
  4. agentnode_sdk-0.4.1/PKG-INFO +219 -0
  5. agentnode_sdk-0.4.1/README.md +196 -0
  6. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode.lock +23 -23
  7. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/__init__.py +8 -0
  8. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/async_client.py +156 -139
  9. agentnode_sdk-0.4.1/agentnode_sdk/cli/__init__.py +1 -0
  10. agentnode_sdk-0.4.1/agentnode_sdk/cli/__main__.py +5 -0
  11. agentnode_sdk-0.4.1/agentnode_sdk/cli/commands.py +405 -0
  12. agentnode_sdk-0.4.1/agentnode_sdk/cli/main.py +125 -0
  13. agentnode_sdk-0.4.1/agentnode_sdk/cli/output.py +48 -0
  14. agentnode_sdk-0.4.1/agentnode_sdk/cli/setup_wizard.py +128 -0
  15. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/client.py +1021 -940
  16. agentnode_sdk-0.4.1/agentnode_sdk/compatibility.py +139 -0
  17. agentnode_sdk-0.4.1/agentnode_sdk/config.py +159 -0
  18. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/detect.py +200 -200
  19. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/installer.py +500 -453
  20. agentnode_sdk-0.4.1/agentnode_sdk/policy.py +15 -0
  21. agentnode_sdk-0.4.1/agentnode_sdk/runner.py +99 -0
  22. agentnode_sdk-0.4.1/agentnode_sdk/runtime.py +1279 -0
  23. agentnode_sdk-0.4.1/agentnode_sdk/runtimes/__init__.py +5 -0
  24. agentnode_sdk-0.4.1/agentnode_sdk/runtimes/mcp_runner.py +270 -0
  25. agentnode_sdk-0.4.0/agentnode_sdk/runner.py → agentnode_sdk-0.4.1/agentnode_sdk/runtimes/python_runner.py +325 -298
  26. agentnode_sdk-0.4.1/agentnode_sdk/runtimes/remote_runner.py +25 -0
  27. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/pyproject.toml +37 -34
  28. agentnode_sdk-0.4.1/scripts/analyze_scores.py +328 -0
  29. agentnode_sdk-0.4.1/scripts/batch_verify.py +422 -0
  30. agentnode_sdk-0.4.1/scripts/ci_smoke_test.py +180 -0
  31. agentnode_sdk-0.4.1/scripts/generate_compatibility_artifacts.py +397 -0
  32. agentnode_sdk-0.4.1/scripts/verify_toolcalls.py +328 -0
  33. agentnode_sdk-0.4.1/scripts/weekly_retest.sh +139 -0
  34. agentnode_sdk-0.4.1/tests/conftest.py +233 -0
  35. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_async_client.py +343 -283
  36. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_auto_upgrade_policy.py +119 -119
  37. agentnode_sdk-0.4.1/tests/test_cli.py +308 -0
  38. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_client.py +187 -152
  39. agentnode_sdk-0.4.1/tests/test_client_sprint_b.py +159 -0
  40. agentnode_sdk-0.4.1/tests/test_config.py +222 -0
  41. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_detect.py +210 -210
  42. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_detect_and_install.py +170 -170
  43. agentnode_sdk-0.4.1/tests/test_e2e_runtime.py +1156 -0
  44. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_edge_cases.py +442 -442
  45. agentnode_sdk-0.4.1/tests/test_installer_sprint_b.py +51 -0
  46. agentnode_sdk-0.4.1/tests/test_provider_matrix.py +967 -0
  47. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_runner.py +355 -315
  48. agentnode_sdk-0.4.1/tests/test_runtime.py +885 -0
  49. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_smart.py +345 -345
  50. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/test_v02.py +210 -210
  51. agentnode_sdk-0.4.0/PKG-INFO +0 -113
  52. agentnode_sdk-0.4.0/README.md +0 -90
  53. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/exceptions.py +0 -0
  54. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/agentnode_sdk/models.py +0 -0
  55. {agentnode_sdk-0.4.0 → agentnode_sdk-0.4.1}/tests/__init__.py +0 -0
@@ -1,8 +1,8 @@
1
- # AgentNode SDK — Environment Variables (optional)
2
- # These can be passed to AgentNode() constructor instead.
3
-
4
- # API endpoint
5
- AGENTNODE_API_URL=https://api.agentnode.net
6
-
7
- # API key
8
- AGENTNODE_API_KEY=ank_your-api-key-here
1
+ # AgentNode SDK — Environment Variables (optional)
2
+ # These can be passed to AgentNode() constructor instead.
3
+
4
+ # API endpoint
5
+ AGENTNODE_API_URL=https://api.agentnode.net
6
+
7
+ # API key
8
+ AGENTNODE_API_KEY=ank_your-api-key-here
@@ -40,6 +40,9 @@ htmlcov/
40
40
  *.tar.gz
41
41
  *.whl
42
42
 
43
+ # Test score artifacts
44
+ .artifacts/
45
+
43
46
  # Spec documents
44
47
  *.docx
45
48
 
@@ -65,3 +68,12 @@ packages_dump.json
65
68
  snapshot_nonowner.txt
66
69
  seo/
67
70
  backend/scripts/enrichment_*.json
71
+
72
+ # Internal documentation (not for GitHub)
73
+ internal/
74
+
75
+ # Internal ops scripts (crawl, enrichment, import)
76
+ scripts/crawl_*.py
77
+ scripts/enrich_*.py
78
+ scripts/import_candidates.py
79
+ candidates*.json
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ ## 0.4.1 — Security & Correctness
4
+
5
+ **Behavioral change:** `run_tool(mode="auto")` now always executes via
6
+ subprocess isolation, regardless of trust level. This makes the
7
+ documented isolation guarantee true by default. `mode="direct"` remains
8
+ available as an explicit opt-in for performance-critical workloads that
9
+ knowingly share in-process globals.
10
+
11
+ **Migration note:** Tools that rely on shared in-process state
12
+ (module-level globals, process-wide singletons) should explicitly pass
13
+ `mode="direct"` going forward.
14
+
15
+ ### Fixes
16
+
17
+ - **AsyncAgentNode /v1 base URL** — the async client now appends `/v1` to
18
+ `base_url` when missing, matching `AgentNode` (sync). Previously all
19
+ `AsyncAgentNode` calls hit `/packages/...` and 404ed against
20
+ production. (P0-04)
21
+ - **AgentNodeClient.install()** now POSTs
22
+ `POST /v1/packages/{slug}/install` so the backend tracks the install
23
+ event. Previously installs went untracked. (P0-05)
24
+ - **run_tool(mode="auto") always uses subprocess** — see behavioral
25
+ change above. (P0-06)
26
+ - **Response parsing hardening** — `_handle`/`_request` no longer crash
27
+ on non-dict JSON error bodies or HTML/plain-text 2xx responses; both
28
+ are now surfaced as `AgentNodeError`. (P1-SDK3, P1-SDK4)
29
+ - **run_tool reserved kwargs** — passing the internal `entry` kwarg via
30
+ `**kwargs` now raises `TypeError` instead of silently shadowing the
31
+ dispatcher's forwarding path. (P1-SDK5)
32
+ - **Installer download ceiling** — `download_artifact` now enforces a
33
+ 500 MB hard ceiling (`MAX_DOWNLOAD_BYTES`). Declared
34
+ `Content-Length` is checked up front; streamed bytes are checked per
35
+ chunk. Oversized downloads are aborted and the partial file removed.
36
+ (P1-SDK6)
37
+ - **run_tool dispatch logging** — `runner.run_tool` now emits an `INFO`
38
+ log line with the resolved runtime and mode, so callers can confirm
39
+ what mode `auto` actually picked without inspecting the
40
+ `RunToolResult` after the fact. (P1-SDK10)
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentnode-sdk
3
+ Version: 0.4.1
4
+ Summary: Python SDK for AgentNode — the open upgrade and discovery infrastructure for AI agents.
5
+ Project-URL: Homepage, https://agentnode.net
6
+ Project-URL: Repository, https://github.com/agentnode-ai/agentnode
7
+ Project-URL: Documentation, https://agentnode.net/docs
8
+ License-Expression: MIT
9
+ Keywords: agent,agentnode,ai,capabilities,langchain,mcp
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: httpx>=0.25
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest; extra == 'dev'
20
+ Requires-Dist: pytest-asyncio; extra == 'dev'
21
+ Requires-Dist: respx; extra == 'dev'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # agentnode-sdk
25
+
26
+ Python SDK for [AgentNode](https://agentnode.net) — the open upgrade and discovery infrastructure for AI agents.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install agentnode-sdk
32
+ ```
33
+
34
+ ## Quick Start — LLM Agent Runtime
35
+
36
+ Connect any LLM agent to AgentNode in three lines. The Runtime provides tool definitions, system prompt, and a tool-loop engine. Tested across 22 models — works with OpenAI, Anthropic, Gemini, Mistral, DeepSeek, Qwen, Llama, and more.
37
+
38
+ ```python
39
+ from agentnode_sdk import AgentNodeRuntime
40
+
41
+ runtime = AgentNodeRuntime()
42
+
43
+ # Get tools + system prompt for your provider
44
+ bundle = runtime.tool_bundle()
45
+ # → { "tools": [...], "system_prompt": "..." }
46
+ ```
47
+
48
+ ### OpenAI
49
+
50
+ ```python
51
+ from openai import OpenAI
52
+ from agentnode_sdk import AgentNodeRuntime
53
+
54
+ runtime = AgentNodeRuntime()
55
+ client = OpenAI()
56
+
57
+ result = runtime.run(
58
+ provider="openai",
59
+ client=client,
60
+ model="gpt-4o",
61
+ messages=[{"role": "user", "content": "Count the words in 'Hello world'"}],
62
+ )
63
+ print(result.content)
64
+ ```
65
+
66
+ ### Anthropic
67
+
68
+ ```python
69
+ from anthropic import Anthropic
70
+ from agentnode_sdk import AgentNodeRuntime
71
+
72
+ runtime = AgentNodeRuntime()
73
+ client = Anthropic()
74
+
75
+ result = runtime.run(
76
+ provider="anthropic",
77
+ client=client,
78
+ model="claude-sonnet-4-6",
79
+ messages=[{"role": "user", "content": "Search for PDF tools on AgentNode"}],
80
+ )
81
+ ```
82
+
83
+ ### Gemini
84
+
85
+ ```python
86
+ from google import genai
87
+ from agentnode_sdk import AgentNodeRuntime
88
+
89
+ runtime = AgentNodeRuntime()
90
+ client = genai.Client()
91
+
92
+ result = runtime.run(
93
+ provider="gemini",
94
+ client=client,
95
+ model="gemini-2.5-flash",
96
+ messages=[{"role": "user", "content": "What AgentNode tools are available?"}],
97
+ )
98
+ ```
99
+
100
+ ### OpenRouter (Mistral, DeepSeek, Qwen, Llama, and more)
101
+
102
+ Use any OpenAI-compatible provider by passing a custom `base_url`:
103
+
104
+ ```python
105
+ from openai import OpenAI
106
+ from agentnode_sdk import AgentNodeRuntime
107
+
108
+ runtime = AgentNodeRuntime()
109
+ client = OpenAI(
110
+ api_key="sk-or-...",
111
+ base_url="https://openrouter.ai/api/v1",
112
+ )
113
+
114
+ result = runtime.run(
115
+ provider="openai",
116
+ client=client,
117
+ model="mistralai/mistral-large", # or deepseek/deepseek-chat, qwen/qwen-plus, etc.
118
+ messages=[{"role": "user", "content": "Find and install a PDF reader tool"}],
119
+ )
120
+ ```
121
+
122
+ ### Generic / Manual Tool Calling
123
+
124
+ For any provider that supports tool calling, use `handle()` to dispatch calls manually:
125
+
126
+ ```python
127
+ runtime = AgentNodeRuntime()
128
+
129
+ # Get tool definitions in your provider's format
130
+ tools = runtime.as_openai_tools() # OpenAI format
131
+ tools = runtime.as_anthropic_tools() # Anthropic format
132
+ tools = runtime.as_gemini_tools() # Gemini format
133
+ tools = runtime.as_generic_tools() # Generic format
134
+
135
+ # When the LLM makes a tool call, dispatch it:
136
+ result = runtime.handle("agentnode_search", {"query": "pdf extraction"})
137
+ # → {"success": true, "result": {"total": 5, "results": [...]}}
138
+ ```
139
+
140
+ ## Three Surfaces
141
+
142
+ ```
143
+ CLI → for humans (search, install, publish)
144
+ SDK / Client → for programmatic access (search, resolve, install, run)
145
+ Runtime → for LLM agents (tool registration, dispatch, auto-loop)
146
+ ```
147
+
148
+ ## API Reference
149
+
150
+ ### `AgentNodeRuntime`
151
+
152
+ Zero-config LLM agent integration.
153
+
154
+ | Method | Description |
155
+ |--------|-------------|
156
+ | `tool_specs()` | Internal typed tool definitions (`list[ToolSpec]`) |
157
+ | `as_openai_tools()` | Tools in OpenAI function-calling format |
158
+ | `as_anthropic_tools()` | Tools in Anthropic format |
159
+ | `as_generic_tools()` | Tools in generic/baseline format |
160
+ | `system_prompt()` | AgentNode system prompt block (append to yours) |
161
+ | `tool_bundle()` | Combined `{"tools": [...], "system_prompt": "..."}` |
162
+ | `handle(tool_name, arguments)` | Dispatch a tool call. Returns dict. Never throws. |
163
+ | `run(provider, client, messages, model, ...)` | Auto-loop with tool dispatch. Never throws. |
164
+
165
+ **Constructor:**
166
+
167
+ ```python
168
+ AgentNodeRuntime(
169
+ client=None, # Optional AgentNodeClient
170
+ api_key=None, # Optional API key
171
+ minimum_trust_level="verified", # "verified" | "trusted" | "curated"
172
+ )
173
+ ```
174
+
175
+ **5 Meta-Tools** (automatically registered):
176
+
177
+ | Tool | Description |
178
+ |------|-------------|
179
+ | `agentnode_capabilities` | List installed packages (local, no API call) |
180
+ | `agentnode_search` | Search the registry (max 5 results) |
181
+ | `agentnode_install` | Install a package by slug |
182
+ | `agentnode_run` | Execute an installed tool |
183
+ | `agentnode_acquire` | Search + install in one step |
184
+
185
+ ### `AgentNodeClient`
186
+
187
+ The programmatic client with typed return models.
188
+
189
+ | Method | Description |
190
+ |--------|-------------|
191
+ | `search(query, ...)` | Search packages by keyword or capability |
192
+ | `resolve(capabilities, ...)` | Resolve capability gaps to ranked packages |
193
+ | `install(slug, ...)` | Download, verify, and install locally |
194
+ | `resolve_and_install(capabilities, ...)` | Resolve + install in one call |
195
+ | `run_tool(slug, tool_name=, ...)` | Run a tool with trust-aware isolation |
196
+ | `smart_run(fn, ...)` | Wrap logic with auto-detect, install, retry |
197
+ | `detect_and_install(error, ...)` | Detect capability gap and install |
198
+
199
+ ### `run_tool()` (standalone)
200
+
201
+ Top-level function for running tools with process isolation.
202
+
203
+ ```python
204
+ from agentnode_sdk import run_tool
205
+
206
+ result = run_tool("pdf-reader-pack", mode="auto", file_path="report.pdf")
207
+ # result.success, result.result, result.error, result.mode_used, result.duration_ms
208
+ ```
209
+
210
+ **Isolation contract.** `mode="auto"` always resolves to `subprocess`,
211
+ regardless of the package's trust level. This makes the isolation
212
+ guarantee true by default. If you need in-process execution (for
213
+ example, to share module-level state with the tool), pass
214
+ `mode="direct"` explicitly — that is an opt-in performance trade-off,
215
+ not a default.
216
+
217
+ ## License
218
+
219
+ MIT
@@ -0,0 +1,196 @@
1
+ # agentnode-sdk
2
+
3
+ Python SDK for [AgentNode](https://agentnode.net) — the open upgrade and discovery infrastructure for AI agents.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install agentnode-sdk
9
+ ```
10
+
11
+ ## Quick Start — LLM Agent Runtime
12
+
13
+ Connect any LLM agent to AgentNode in three lines. The Runtime provides tool definitions, system prompt, and a tool-loop engine. Tested across 22 models — works with OpenAI, Anthropic, Gemini, Mistral, DeepSeek, Qwen, Llama, and more.
14
+
15
+ ```python
16
+ from agentnode_sdk import AgentNodeRuntime
17
+
18
+ runtime = AgentNodeRuntime()
19
+
20
+ # Get tools + system prompt for your provider
21
+ bundle = runtime.tool_bundle()
22
+ # → { "tools": [...], "system_prompt": "..." }
23
+ ```
24
+
25
+ ### OpenAI
26
+
27
+ ```python
28
+ from openai import OpenAI
29
+ from agentnode_sdk import AgentNodeRuntime
30
+
31
+ runtime = AgentNodeRuntime()
32
+ client = OpenAI()
33
+
34
+ result = runtime.run(
35
+ provider="openai",
36
+ client=client,
37
+ model="gpt-4o",
38
+ messages=[{"role": "user", "content": "Count the words in 'Hello world'"}],
39
+ )
40
+ print(result.content)
41
+ ```
42
+
43
+ ### Anthropic
44
+
45
+ ```python
46
+ from anthropic import Anthropic
47
+ from agentnode_sdk import AgentNodeRuntime
48
+
49
+ runtime = AgentNodeRuntime()
50
+ client = Anthropic()
51
+
52
+ result = runtime.run(
53
+ provider="anthropic",
54
+ client=client,
55
+ model="claude-sonnet-4-6",
56
+ messages=[{"role": "user", "content": "Search for PDF tools on AgentNode"}],
57
+ )
58
+ ```
59
+
60
+ ### Gemini
61
+
62
+ ```python
63
+ from google import genai
64
+ from agentnode_sdk import AgentNodeRuntime
65
+
66
+ runtime = AgentNodeRuntime()
67
+ client = genai.Client()
68
+
69
+ result = runtime.run(
70
+ provider="gemini",
71
+ client=client,
72
+ model="gemini-2.5-flash",
73
+ messages=[{"role": "user", "content": "What AgentNode tools are available?"}],
74
+ )
75
+ ```
76
+
77
+ ### OpenRouter (Mistral, DeepSeek, Qwen, Llama, and more)
78
+
79
+ Use any OpenAI-compatible provider by passing a custom `base_url`:
80
+
81
+ ```python
82
+ from openai import OpenAI
83
+ from agentnode_sdk import AgentNodeRuntime
84
+
85
+ runtime = AgentNodeRuntime()
86
+ client = OpenAI(
87
+ api_key="sk-or-...",
88
+ base_url="https://openrouter.ai/api/v1",
89
+ )
90
+
91
+ result = runtime.run(
92
+ provider="openai",
93
+ client=client,
94
+ model="mistralai/mistral-large", # or deepseek/deepseek-chat, qwen/qwen-plus, etc.
95
+ messages=[{"role": "user", "content": "Find and install a PDF reader tool"}],
96
+ )
97
+ ```
98
+
99
+ ### Generic / Manual Tool Calling
100
+
101
+ For any provider that supports tool calling, use `handle()` to dispatch calls manually:
102
+
103
+ ```python
104
+ runtime = AgentNodeRuntime()
105
+
106
+ # Get tool definitions in your provider's format
107
+ tools = runtime.as_openai_tools() # OpenAI format
108
+ tools = runtime.as_anthropic_tools() # Anthropic format
109
+ tools = runtime.as_gemini_tools() # Gemini format
110
+ tools = runtime.as_generic_tools() # Generic format
111
+
112
+ # When the LLM makes a tool call, dispatch it:
113
+ result = runtime.handle("agentnode_search", {"query": "pdf extraction"})
114
+ # → {"success": true, "result": {"total": 5, "results": [...]}}
115
+ ```
116
+
117
+ ## Three Surfaces
118
+
119
+ ```
120
+ CLI → for humans (search, install, publish)
121
+ SDK / Client → for programmatic access (search, resolve, install, run)
122
+ Runtime → for LLM agents (tool registration, dispatch, auto-loop)
123
+ ```
124
+
125
+ ## API Reference
126
+
127
+ ### `AgentNodeRuntime`
128
+
129
+ Zero-config LLM agent integration.
130
+
131
+ | Method | Description |
132
+ |--------|-------------|
133
+ | `tool_specs()` | Internal typed tool definitions (`list[ToolSpec]`) |
134
+ | `as_openai_tools()` | Tools in OpenAI function-calling format |
135
+ | `as_anthropic_tools()` | Tools in Anthropic format |
136
+ | `as_generic_tools()` | Tools in generic/baseline format |
137
+ | `system_prompt()` | AgentNode system prompt block (append to yours) |
138
+ | `tool_bundle()` | Combined `{"tools": [...], "system_prompt": "..."}` |
139
+ | `handle(tool_name, arguments)` | Dispatch a tool call. Returns dict. Never throws. |
140
+ | `run(provider, client, messages, model, ...)` | Auto-loop with tool dispatch. Never throws. |
141
+
142
+ **Constructor:**
143
+
144
+ ```python
145
+ AgentNodeRuntime(
146
+ client=None, # Optional AgentNodeClient
147
+ api_key=None, # Optional API key
148
+ minimum_trust_level="verified", # "verified" | "trusted" | "curated"
149
+ )
150
+ ```
151
+
152
+ **5 Meta-Tools** (automatically registered):
153
+
154
+ | Tool | Description |
155
+ |------|-------------|
156
+ | `agentnode_capabilities` | List installed packages (local, no API call) |
157
+ | `agentnode_search` | Search the registry (max 5 results) |
158
+ | `agentnode_install` | Install a package by slug |
159
+ | `agentnode_run` | Execute an installed tool |
160
+ | `agentnode_acquire` | Search + install in one step |
161
+
162
+ ### `AgentNodeClient`
163
+
164
+ The programmatic client with typed return models.
165
+
166
+ | Method | Description |
167
+ |--------|-------------|
168
+ | `search(query, ...)` | Search packages by keyword or capability |
169
+ | `resolve(capabilities, ...)` | Resolve capability gaps to ranked packages |
170
+ | `install(slug, ...)` | Download, verify, and install locally |
171
+ | `resolve_and_install(capabilities, ...)` | Resolve + install in one call |
172
+ | `run_tool(slug, tool_name=, ...)` | Run a tool with trust-aware isolation |
173
+ | `smart_run(fn, ...)` | Wrap logic with auto-detect, install, retry |
174
+ | `detect_and_install(error, ...)` | Detect capability gap and install |
175
+
176
+ ### `run_tool()` (standalone)
177
+
178
+ Top-level function for running tools with process isolation.
179
+
180
+ ```python
181
+ from agentnode_sdk import run_tool
182
+
183
+ result = run_tool("pdf-reader-pack", mode="auto", file_path="report.pdf")
184
+ # result.success, result.result, result.error, result.mode_used, result.duration_ms
185
+ ```
186
+
187
+ **Isolation contract.** `mode="auto"` always resolves to `subprocess`,
188
+ regardless of the package's trust level. This makes the isolation
189
+ guarantee true by default. If you need in-process execution (for
190
+ example, to share module-level state with the tool), pass
191
+ `mode="direct"` explicitly — that is an opt-in performance trade-off,
192
+ not a default.
193
+
194
+ ## License
195
+
196
+ MIT
@@ -1,23 +1,23 @@
1
- {
2
- "lockfile_version": "0.1",
3
- "updated_at": "2026-03-18T02:18:53.827839+00:00",
4
- "packages": {
5
- "word-counter-pack": {
6
- "version": "1.0.0",
7
- "package_type": "toolpack",
8
- "entrypoint": "word_counter_pack.tool",
9
- "capability_ids": [
10
- "data_cleaning"
11
- ],
12
- "tools": [
13
- {
14
- "name": "count_words",
15
- "entrypoint": "word_counter_pack.tool:count_words"
16
- }
17
- ],
18
- "artifact_hash": "sha256:445388c86aa2b20c3e748f58b2d221548f1f3f71ff5c715a64cdc80966fab03c",
19
- "installed_at": "2026-03-18T02:18:53.827396+00:00",
20
- "source": "sdk"
21
- }
22
- }
23
- }
1
+ {
2
+ "lockfile_version": "0.1",
3
+ "updated_at": "2026-03-18T02:18:53.827839+00:00",
4
+ "packages": {
5
+ "word-counter-pack": {
6
+ "version": "1.0.0",
7
+ "package_type": "toolpack",
8
+ "entrypoint": "word_counter_pack.tool",
9
+ "capability_ids": [
10
+ "data_cleaning"
11
+ ],
12
+ "tools": [
13
+ {
14
+ "name": "count_words",
15
+ "entrypoint": "word_counter_pack.tool:count_words"
16
+ }
17
+ ],
18
+ "artifact_hash": "sha256:445388c86aa2b20c3e748f58b2d221548f1f3f71ff5c715a64cdc80966fab03c",
19
+ "installed_at": "2026-03-18T02:18:53.827396+00:00",
20
+ "source": "sdk"
21
+ }
22
+ }
23
+ }
@@ -2,6 +2,7 @@
2
2
 
3
3
  from agentnode_sdk.async_client import AsyncAgentNode
4
4
  from agentnode_sdk.client import AgentNode, AgentNodeClient
5
+ from agentnode_sdk.config import load_config, config_path, installation_behavior_label
5
6
  from agentnode_sdk.detect import detect_gap
6
7
  from agentnode_sdk.exceptions import (
7
8
  AgentNodeError,
@@ -26,7 +27,9 @@ from agentnode_sdk.models import (
26
27
  SearchResult,
27
28
  SmartRunResult,
28
29
  )
30
+ from agentnode_sdk.compatibility import recommend_model
29
31
  from agentnode_sdk.runner import run_tool
32
+ from agentnode_sdk.runtime import AgentNodeRuntime
30
33
 
31
34
  # Convenience aliases
32
35
  Client = AgentNodeClient
@@ -38,6 +41,9 @@ __all__ = [
38
41
  "AsyncAgentNode",
39
42
  "AgentNodeClient",
40
43
  "Client",
44
+ "load_config",
45
+ "config_path",
46
+ "installation_behavior_label",
41
47
  "detect_gap",
42
48
  "load_tool",
43
49
  "run_tool",
@@ -60,4 +66,6 @@ __all__ = [
60
66
  "DetectedGap",
61
67
  "DetectAndInstallResult",
62
68
  "SmartRunResult",
69
+ "AgentNodeRuntime",
70
+ "recommend_model",
63
71
  ]