holokai-neuron-sdk 0.1.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.
@@ -0,0 +1,9 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .mypy_cache/
8
+ build/
9
+ dist/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Holokai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.4
2
+ Name: holokai-neuron-sdk
3
+ Version: 0.1.0
4
+ Summary: SDK for building Holokai neurons in Python — connect to a BigBrain gateway over HTTP+SSE and execute capability-typed tasks.
5
+ Project-URL: Homepage, https://github.com/holok-ai/bigbrain/tree/main/packages/neuron-sdk-python#readme
6
+ Project-URL: Repository, https://github.com/holok-ai/bigbrain
7
+ Project-URL: Issues, https://github.com/holok-ai/bigbrain/issues
8
+ Author: Holokai
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,bigbrain,holokai,neuron,sdk,sse,workflow
12
+ Classifier: Framework :: AsyncIO
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx<1,>=0.27
22
+ Requires-Dist: jsonschema<5,>=4.21
23
+ Requires-Dist: pydantic<3,>=2.6
24
+ Provides-Extra: dev
25
+ Requires-Dist: aiohttp>=3.9; extra == 'dev'
26
+ Requires-Dist: mypy>=1.10; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest>=8; extra == 'dev'
29
+ Requires-Dist: respx>=0.21; extra == 'dev'
30
+ Requires-Dist: ruff>=0.5; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # holokai-neuron-sdk
34
+
35
+ SDK for building **Holokai neurons** in Python — connect to a BigBrain
36
+ gateway over HTTP+SSE and execute capability-typed tasks.
37
+
38
+ This is the Python sibling of [`@holokai/neuron-sdk`][ts-sdk] (TypeScript)
39
+ and speaks the same wire protocol byte-for-byte
40
+ (`packages/neuron-protocol`).
41
+
42
+ [ts-sdk]: ../neuron-sdk
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ pip install holokai-neuron-sdk
48
+ ```
49
+
50
+ Requires Python 3.10+.
51
+
52
+ ## Quick start
53
+
54
+ ```python
55
+ import asyncio
56
+ import logging
57
+
58
+ from holokai_neuron_sdk import Capability, HandlerContext, Neuron
59
+
60
+
61
+ async def echo(input, ctx: HandlerContext):
62
+ await ctx.progress(percent=50, message="halfway")
63
+ return {"echo": input}
64
+
65
+
66
+ async def main():
67
+ neuron = Neuron(
68
+ gateway_url="https://api.holokai.dev",
69
+ neuron_id="my-neuron-1",
70
+ auth=lambda: "<bearer token>", # sync or async; called per request
71
+ logger=logging.getLogger("neuron"),
72
+ )
73
+
74
+ neuron.register_handler(
75
+ Capability(type="example/echo", scope="any", concurrency=4),
76
+ echo,
77
+ input_schema={"type": "object"},
78
+ output_schema={
79
+ "type": "object",
80
+ "properties": {"echo": {}},
81
+ "required": ["echo"],
82
+ },
83
+ )
84
+
85
+ await neuron.start()
86
+ try:
87
+ await asyncio.Event().wait() # run until cancelled
88
+ finally:
89
+ await neuron.stop(drain=True, timeout=30)
90
+
91
+
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ ## Concepts
96
+
97
+ | Concept | What it is |
98
+ | ------- | ---------- |
99
+ | **Neuron** | A process that registers itself with a BigBrain gateway and offers one or more capabilities. |
100
+ | **Capability** | A namespaced task type (`owner/package[/name][.variant]`) with a scope (`"any"` or `{onBehalfOf: userId}`) and a per-capability concurrency. |
101
+ | **Lease** | A single in-flight task delivery. Carries the input, schemas, and a deadline. The neuron acks (success), nacks (failure), or progresses. |
102
+ | **Cancel** | The gateway can revoke a lease mid-flight. The handler's cancellation `asyncio.Event` is set, the task is cancelled, and a `cancelled` nack is sent. |
103
+ | **Heartbeat** | The SDK posts a heartbeat every 10s with the current in-flight lease list. The gateway uses it to detect dead neurons and to renew lease TTLs for long-running tasks. |
104
+
105
+ ## Wire protocol
106
+
107
+ * **Transport**: SSE (server → neuron) + HTTPS POST (neuron → server).
108
+ * **Endpoints**:
109
+ * `GET /neuron/events?neuronId=…` — SSE stream
110
+ * `POST /neuron/{register, update-capability, heartbeat, ack, nack, progress}`
111
+ * **Authentication**: `Authorization: Bearer <jwt>`. The `auth` callback is
112
+ invoked on every POST and SSE open, and is given one chance to refresh on
113
+ 401 before the SDK escalates to reconnect-with-backoff.
114
+ * **Schemas**: input/output JSON Schema arrives on the lease frame; the SDK
115
+ validates with `jsonschema` and emits a `schema-mismatch` nack on failure.
116
+ * **Versioning**: `PROTOCOL_VERSION = "1.0.0"` (free-form on the wire; the
117
+ gateway negotiates compatibility).
118
+
119
+ ## Handler contract
120
+
121
+ ```python
122
+ async def handler(input, ctx: HandlerContext):
123
+ # ctx.task — the full task payload
124
+ # ctx.lease_id — the lease the gateway holds for this delivery
125
+ # ctx.cancelled — asyncio.Event set on cancel / shutdown
126
+ # ctx.log — logger scoped to this lease
127
+ # ctx.progress(...) — non-blocking progress update
128
+ # ctx.fail(reason, code=...) — terminal nack (do not catch)
129
+ return {...}
130
+ ```
131
+
132
+ * **Sync handlers** are supported; the runner awaits awaitable return values
133
+ and otherwise treats the return as the result.
134
+ * **Cancellation**: handlers wrapping I/O should cooperate with
135
+ `ctx.cancelled` (e.g. `asyncio.wait` with `[ctx.cancelled.wait(), …]`).
136
+ * **Idempotency** is the handler author's responsibility — the framework
137
+ does not checkpoint mid-task.
138
+
139
+ ## Failure classification
140
+
141
+ | Outcome | Wire kind |
142
+ |--------------------------------------|--------------------|
143
+ | Handler returns | `ack` |
144
+ | Handler raises `asyncio.CancelledError` (or cancel event set) | `nack: cancelled` |
145
+ | `ctx.fail(...)` | `nack: terminal` |
146
+ | Handler raises any other exception | `nack: retryable` |
147
+ | Input/output fails JSON Schema | `nack: schema-mismatch` |
148
+
149
+ Retry policy lives on the workflow (server-side), never on the SDK.
150
+
151
+ ## Architecture
152
+
153
+ ```
154
+ ┌────────────┐ POST register / heartbeat / ack / nack / progress
155
+ │ Neuron │──────────────────────────────────────────────────────▶│
156
+ │ (this │ │ BigBrain
157
+ │ SDK) │◀──────────────────────────── SSE: lease / cancel ────│ gateway
158
+ └────────────┘
159
+ ```
160
+
161
+ * `HttpTransport` owns one SSE stream and a shared `httpx.AsyncClient`.
162
+ * `Neuron` wires the transport to a heartbeat loop and a per-capability
163
+ semaphore-bounded dispatcher.
164
+ * `run_lease(...)` validates input, invokes the handler, validates output,
165
+ and posts the right ack/nack frame.
166
+
167
+ ## Examples
168
+
169
+ | Example | Capability | What it does |
170
+ | ------- | ---------- | ------------ |
171
+ | [`examples/http_fetch/`](examples/http_fetch/) | `examples/http.fetch` | Fetches an arbitrary HTTP(S) URL via `httpx` and returns status/headers/body. |
172
+ | [`examples/web_search/`](examples/web_search/) | `examples/web.search` | Keyless web search via DuckDuckGo HTML scrape. No API key, but inherently brittle — see the example README for caveats. |
173
+
174
+ Each ships with input/output JSON Schemas, cooperative cancellation
175
+ (`ctx.cancelled`), and a CLI runner. Run them the same way:
176
+
177
+ ```bash
178
+ pip install -e .
179
+ BIGBRAIN_GATEWAY_URL=https://api.holokai.dev \
180
+ BIGBRAIN_NEURON_ID=my-python-neuron-1 \
181
+ BIGBRAIN_TOKEN=eyJ... \
182
+ python -m examples.http_fetch # or examples.web_search
183
+ ```
184
+
185
+ ## Custom transports
186
+
187
+ `HttpTransport` is the default but the public `Transport` shape is documented
188
+ on `TransportCallbacks` and `Neuron(transport=…)` accepts any object that
189
+ matches the protocol — handy for tests or in-process embeddings.
190
+
191
+ ## Tests
192
+
193
+ ```bash
194
+ # Unit + deterministic e2e (default — no network).
195
+ pytest
196
+
197
+ # Network-gated e2e: hits real DuckDuckGo through the real SDK to catch
198
+ # scraper drift. Skipped unless explicitly enabled.
199
+ E2E_NETWORK=1 pytest -m e2e_network
200
+ ```
201
+
202
+ The e2e tests stand up a tiny aiohttp server on loopback that serves both
203
+ the BigBrain `/neuron/*` surface and a stub for DuckDuckGo, then run the
204
+ real `Neuron` SDK against it. Every byte flows over real HTTP — SSE in,
205
+ POSTs out — exercising the full `register → lease → handler → ack` loop.
206
+ See [`tests/e2e/`](tests/e2e/).
207
+
208
+ ## License
209
+
210
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,178 @@
1
+ # holokai-neuron-sdk
2
+
3
+ SDK for building **Holokai neurons** in Python — connect to a BigBrain
4
+ gateway over HTTP+SSE and execute capability-typed tasks.
5
+
6
+ This is the Python sibling of [`@holokai/neuron-sdk`][ts-sdk] (TypeScript)
7
+ and speaks the same wire protocol byte-for-byte
8
+ (`packages/neuron-protocol`).
9
+
10
+ [ts-sdk]: ../neuron-sdk
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install holokai-neuron-sdk
16
+ ```
17
+
18
+ Requires Python 3.10+.
19
+
20
+ ## Quick start
21
+
22
+ ```python
23
+ import asyncio
24
+ import logging
25
+
26
+ from holokai_neuron_sdk import Capability, HandlerContext, Neuron
27
+
28
+
29
+ async def echo(input, ctx: HandlerContext):
30
+ await ctx.progress(percent=50, message="halfway")
31
+ return {"echo": input}
32
+
33
+
34
+ async def main():
35
+ neuron = Neuron(
36
+ gateway_url="https://api.holokai.dev",
37
+ neuron_id="my-neuron-1",
38
+ auth=lambda: "<bearer token>", # sync or async; called per request
39
+ logger=logging.getLogger("neuron"),
40
+ )
41
+
42
+ neuron.register_handler(
43
+ Capability(type="example/echo", scope="any", concurrency=4),
44
+ echo,
45
+ input_schema={"type": "object"},
46
+ output_schema={
47
+ "type": "object",
48
+ "properties": {"echo": {}},
49
+ "required": ["echo"],
50
+ },
51
+ )
52
+
53
+ await neuron.start()
54
+ try:
55
+ await asyncio.Event().wait() # run until cancelled
56
+ finally:
57
+ await neuron.stop(drain=True, timeout=30)
58
+
59
+
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ ## Concepts
64
+
65
+ | Concept | What it is |
66
+ | ------- | ---------- |
67
+ | **Neuron** | A process that registers itself with a BigBrain gateway and offers one or more capabilities. |
68
+ | **Capability** | A namespaced task type (`owner/package[/name][.variant]`) with a scope (`"any"` or `{onBehalfOf: userId}`) and a per-capability concurrency. |
69
+ | **Lease** | A single in-flight task delivery. Carries the input, schemas, and a deadline. The neuron acks (success), nacks (failure), or progresses. |
70
+ | **Cancel** | The gateway can revoke a lease mid-flight. The handler's cancellation `asyncio.Event` is set, the task is cancelled, and a `cancelled` nack is sent. |
71
+ | **Heartbeat** | The SDK posts a heartbeat every 10s with the current in-flight lease list. The gateway uses it to detect dead neurons and to renew lease TTLs for long-running tasks. |
72
+
73
+ ## Wire protocol
74
+
75
+ * **Transport**: SSE (server → neuron) + HTTPS POST (neuron → server).
76
+ * **Endpoints**:
77
+ * `GET /neuron/events?neuronId=…` — SSE stream
78
+ * `POST /neuron/{register, update-capability, heartbeat, ack, nack, progress}`
79
+ * **Authentication**: `Authorization: Bearer <jwt>`. The `auth` callback is
80
+ invoked on every POST and SSE open, and is given one chance to refresh on
81
+ 401 before the SDK escalates to reconnect-with-backoff.
82
+ * **Schemas**: input/output JSON Schema arrives on the lease frame; the SDK
83
+ validates with `jsonschema` and emits a `schema-mismatch` nack on failure.
84
+ * **Versioning**: `PROTOCOL_VERSION = "1.0.0"` (free-form on the wire; the
85
+ gateway negotiates compatibility).
86
+
87
+ ## Handler contract
88
+
89
+ ```python
90
+ async def handler(input, ctx: HandlerContext):
91
+ # ctx.task — the full task payload
92
+ # ctx.lease_id — the lease the gateway holds for this delivery
93
+ # ctx.cancelled — asyncio.Event set on cancel / shutdown
94
+ # ctx.log — logger scoped to this lease
95
+ # ctx.progress(...) — non-blocking progress update
96
+ # ctx.fail(reason, code=...) — terminal nack (do not catch)
97
+ return {...}
98
+ ```
99
+
100
+ * **Sync handlers** are supported; the runner awaits awaitable return values
101
+ and otherwise treats the return as the result.
102
+ * **Cancellation**: handlers wrapping I/O should cooperate with
103
+ `ctx.cancelled` (e.g. `asyncio.wait` with `[ctx.cancelled.wait(), …]`).
104
+ * **Idempotency** is the handler author's responsibility — the framework
105
+ does not checkpoint mid-task.
106
+
107
+ ## Failure classification
108
+
109
+ | Outcome | Wire kind |
110
+ |--------------------------------------|--------------------|
111
+ | Handler returns | `ack` |
112
+ | Handler raises `asyncio.CancelledError` (or cancel event set) | `nack: cancelled` |
113
+ | `ctx.fail(...)` | `nack: terminal` |
114
+ | Handler raises any other exception | `nack: retryable` |
115
+ | Input/output fails JSON Schema | `nack: schema-mismatch` |
116
+
117
+ Retry policy lives on the workflow (server-side), never on the SDK.
118
+
119
+ ## Architecture
120
+
121
+ ```
122
+ ┌────────────┐ POST register / heartbeat / ack / nack / progress
123
+ │ Neuron │──────────────────────────────────────────────────────▶│
124
+ │ (this │ │ BigBrain
125
+ │ SDK) │◀──────────────────────────── SSE: lease / cancel ────│ gateway
126
+ └────────────┘
127
+ ```
128
+
129
+ * `HttpTransport` owns one SSE stream and a shared `httpx.AsyncClient`.
130
+ * `Neuron` wires the transport to a heartbeat loop and a per-capability
131
+ semaphore-bounded dispatcher.
132
+ * `run_lease(...)` validates input, invokes the handler, validates output,
133
+ and posts the right ack/nack frame.
134
+
135
+ ## Examples
136
+
137
+ | Example | Capability | What it does |
138
+ | ------- | ---------- | ------------ |
139
+ | [`examples/http_fetch/`](examples/http_fetch/) | `examples/http.fetch` | Fetches an arbitrary HTTP(S) URL via `httpx` and returns status/headers/body. |
140
+ | [`examples/web_search/`](examples/web_search/) | `examples/web.search` | Keyless web search via DuckDuckGo HTML scrape. No API key, but inherently brittle — see the example README for caveats. |
141
+
142
+ Each ships with input/output JSON Schemas, cooperative cancellation
143
+ (`ctx.cancelled`), and a CLI runner. Run them the same way:
144
+
145
+ ```bash
146
+ pip install -e .
147
+ BIGBRAIN_GATEWAY_URL=https://api.holokai.dev \
148
+ BIGBRAIN_NEURON_ID=my-python-neuron-1 \
149
+ BIGBRAIN_TOKEN=eyJ... \
150
+ python -m examples.http_fetch # or examples.web_search
151
+ ```
152
+
153
+ ## Custom transports
154
+
155
+ `HttpTransport` is the default but the public `Transport` shape is documented
156
+ on `TransportCallbacks` and `Neuron(transport=…)` accepts any object that
157
+ matches the protocol — handy for tests or in-process embeddings.
158
+
159
+ ## Tests
160
+
161
+ ```bash
162
+ # Unit + deterministic e2e (default — no network).
163
+ pytest
164
+
165
+ # Network-gated e2e: hits real DuckDuckGo through the real SDK to catch
166
+ # scraper drift. Skipped unless explicitly enabled.
167
+ E2E_NETWORK=1 pytest -m e2e_network
168
+ ```
169
+
170
+ The e2e tests stand up a tiny aiohttp server on loopback that serves both
171
+ the BigBrain `/neuron/*` surface and a stub for DuckDuckGo, then run the
172
+ real `Neuron` SDK against it. Every byte flows over real HTTP — SSE in,
173
+ POSTs out — exercising the full `register → lease → handler → ack` loop.
174
+ See [`tests/e2e/`](tests/e2e/).
175
+
176
+ ## License
177
+
178
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,74 @@
1
+ # `examples/http.fetch` — runnable Python neuron
2
+
3
+ Generic outbound HTTP fetcher exposed as a BigBrain capability. A workflow
4
+ plan that resolves to `examples/http.fetch` will arrive at this neuron as a
5
+ lease, run an `httpx` request, and ack with the response.
6
+
7
+ ## Run
8
+
9
+ ```bash
10
+ cd packages/neuron-sdk-python
11
+ pip install -e .
12
+ BIGBRAIN_GATEWAY_URL=https://api.holokai.dev \
13
+ BIGBRAIN_NEURON_ID=my-python-neuron-1 \
14
+ BIGBRAIN_TOKEN=eyJhbGciOi... \
15
+ python -m examples.http_fetch
16
+ ```
17
+
18
+ `BIGBRAIN_TOKEN_FILE=/path/to/token` is supported as an alternative — the
19
+ file is re-read on every auth refresh, so you can rotate the token without
20
+ restarting.
21
+
22
+ ## Capability shape
23
+
24
+ | Field | Value |
25
+ | ----- | ----- |
26
+ | `type` | `examples/http.fetch` |
27
+ | `scope` | `any` |
28
+ | `concurrency` | 8 (handle up to 8 leases in parallel per neuron) |
29
+ | `leaseTtlMs` | 60_000 (longer than the default to cover slow upstreams) |
30
+
31
+ ### Input
32
+
33
+ ```json
34
+ {
35
+ "url": "https://example.com/api/thing",
36
+ "method": "GET",
37
+ "headers": {"User-Agent": "bigbrain-neuron"},
38
+ "body": null,
39
+ "timeout_ms": 10000,
40
+ "max_response_bytes": 1000000,
41
+ "follow_redirects": true
42
+ }
43
+ ```
44
+
45
+ Only `url` is required.
46
+
47
+ ### Output
48
+
49
+ ```json
50
+ {
51
+ "status": 200,
52
+ "headers": {"content-type": "application/json", "...": "..."},
53
+ "body": "{\"hello\":\"world\"}",
54
+ "truncated": false,
55
+ "duration_ms": 87,
56
+ "final_url": "https://example.com/api/thing"
57
+ }
58
+ ```
59
+
60
+ * HTTP non-2xx responses are returned as-is — the workflow author decides
61
+ whether a 4xx/5xx is fatal.
62
+ * Response bodies are decoded as UTF-8 (replacement on errors) and clipped
63
+ to `max_response_bytes`. `truncated: true` means there was more.
64
+ * Network errors (DNS, connect refused, timeout) propagate as a
65
+ `retryable` nack — the workflow's retry policy decides what's next.
66
+ * If the gateway sends a `cancel` frame mid-request the in-flight `httpx`
67
+ call is aborted and the lease is nacked as `cancelled`.
68
+
69
+ ## Files
70
+
71
+ | File | What |
72
+ | ---- | ---- |
73
+ | [`capability.py`](capability.py) | Handler, JSON schemas, `Capability` definition. Importable on its own. |
74
+ | [`__main__.py`](__main__.py) | CLI runner. Reads gateway URL / neuron id / token from env, registers the handler, runs until SIGINT. |
@@ -0,0 +1,80 @@
1
+ # `examples/web.search` — keyless web search
2
+
3
+ Exposes web search to BigBrain workflows by scraping DuckDuckGo's HTML
4
+ endpoint (`https://html.duckduckgo.com/html/`). No API key, no extra
5
+ dependencies beyond `httpx` and stdlib `html.parser`.
6
+
7
+ ## ⚠️ Caveats
8
+
9
+ * **Brittle by design** — DuckDuckGo can change the HTML markup or
10
+ tighten rate-limits at any time. If results stop coming back, look at
11
+ the response (`LOG_LEVEL=DEBUG`) and adjust the parser, or swap in
12
+ another provider.
13
+ * **Rate-limited** — DDG returns HTTP 202 (with no results) when it
14
+ decides you're hitting too hard. The handler surfaces that as a
15
+ `terminal` nack so the workflow author chooses a back-off rather than
16
+ the framework retrying into a tighter ban.
17
+ * **No personalization / safe-search controls** — kept intentionally
18
+ thin. Wire those in via the `region` field (passed through as
19
+ DuckDuckGo's `kl=` parameter) or replace the handler.
20
+
21
+ ## Run
22
+
23
+ ```bash
24
+ cd packages/neuron-sdk-python
25
+ pip install -e .
26
+ BIGBRAIN_GATEWAY_URL=https://api.holokai.dev \
27
+ BIGBRAIN_NEURON_ID=my-python-neuron-1 \
28
+ BIGBRAIN_TOKEN=eyJ... \
29
+ python -m examples.web_search
30
+ ```
31
+
32
+ Optional overrides:
33
+
34
+ | Env var | Default | What it does |
35
+ | ------- | ------- | ------------ |
36
+ | `EXAMPLES_WEB_SEARCH_ENDPOINT` | `https://html.duckduckgo.com/html/` | Swap providers (e.g. a private SearXNG instance — though parser will need to be adjusted to the new HTML shape). |
37
+ | `EXAMPLES_WEB_SEARCH_UA` | a desktop Chrome UA | Set the `User-Agent`. DDG returns empty results for the stock httpx UA. |
38
+
39
+ ## Capability shape
40
+
41
+ | Field | Value |
42
+ | ----- | ----- |
43
+ | `type` | `examples/web.search` |
44
+ | `scope` | `any` |
45
+ | `concurrency` | 4 |
46
+ | `leaseTtlMs` | 30_000 |
47
+
48
+ ### Input
49
+
50
+ ```json
51
+ {
52
+ "query": "neuron protocol holokai",
53
+ "max_results": 10,
54
+ "region": "wt-wt"
55
+ }
56
+ ```
57
+
58
+ Only `query` is required.
59
+
60
+ ### Output
61
+
62
+ ```json
63
+ {
64
+ "query": "neuron protocol holokai",
65
+ "results": [
66
+ {
67
+ "title": "Holokai BigBrain — Neuron architecture",
68
+ "url": "https://example.test/neuron",
69
+ "snippet": "Lease-based capability dispatch over SSE+POST..."
70
+ }
71
+ ]
72
+ }
73
+ ```
74
+
75
+ ## Files
76
+
77
+ | File | What |
78
+ | ---- | ---- |
79
+ | [`capability.py`](capability.py) | Handler, JSON Schemas, `Capability` definition, defensive HTML parser. |
80
+ | [`__main__.py`](__main__.py) | CLI runner. Reads gateway URL / neuron id / token from env, registers the handler, runs until SIGINT. |
@@ -0,0 +1,73 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.24"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "holokai-neuron-sdk"
7
+ version = "0.1.0"
8
+ description = "SDK for building Holokai neurons in Python — connect to a BigBrain gateway over HTTP+SSE and execute capability-typed tasks."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Holokai" }]
13
+ keywords = ["holokai", "bigbrain", "neuron", "sdk", "workflow", "sse", "agent"]
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Framework :: AsyncIO",
21
+ "Intended Audience :: Developers",
22
+ "Topic :: Software Development :: Libraries",
23
+ ]
24
+ dependencies = [
25
+ "httpx>=0.27,<1",
26
+ "pydantic>=2.6,<3",
27
+ "jsonschema>=4.21,<5",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/holok-ai/bigbrain/tree/main/packages/neuron-sdk-python#readme"
32
+ Repository = "https://github.com/holok-ai/bigbrain"
33
+ Issues = "https://github.com/holok-ai/bigbrain/issues"
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=8",
38
+ "pytest-asyncio>=0.23",
39
+ "respx>=0.21",
40
+ "aiohttp>=3.9",
41
+ "mypy>=1.10",
42
+ "ruff>=0.5",
43
+ ]
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["src/holokai_neuron_sdk"]
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ include = ["src/holokai_neuron_sdk", "README.md", "LICENSE", "tests"]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["tests"]
53
+ asyncio_mode = "auto"
54
+ addopts = "-ra"
55
+ pythonpath = ["."]
56
+ markers = [
57
+ "e2e: end-to-end tests that spin up a fake gateway and exercise the full SDK loop",
58
+ "e2e_network: e2e tests that hit the real internet (gated by E2E_NETWORK=1)",
59
+ ]
60
+
61
+ [tool.ruff]
62
+ line-length = 100
63
+ target-version = "py310"
64
+
65
+ [tool.ruff.lint]
66
+ select = ["E", "F", "I", "B", "UP", "N", "ASYNC"]
67
+ ignore = ["E501"]
68
+
69
+ [tool.mypy]
70
+ python_version = "3.10"
71
+ strict = true
72
+ warn_unused_ignores = true
73
+ warn_redundant_casts = true