hebbrix 2.6.1__tar.gz → 2.6.3__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.
- {hebbrix-2.6.1 → hebbrix-2.6.3}/CHANGELOG.md +14 -0
- {hebbrix-2.6.1/hebbrix.egg-info → hebbrix-2.6.3}/PKG-INFO +79 -43
- {hebbrix-2.6.1 → hebbrix-2.6.3}/README.md +77 -41
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/__init__.py +3 -2
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/_advice.py +63 -1
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/chat.py +22 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/client.py +5 -1
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/models.py +16 -1
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/resources.py +65 -5
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/sync_client.py +57 -6
- {hebbrix-2.6.1 → hebbrix-2.6.3/hebbrix.egg-info}/PKG-INFO +79 -43
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix.egg-info/SOURCES.txt +1 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/pyproject.toml +2 -2
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_advisor_integrity.py +30 -0
- hebbrix-2.6.3/tests/test_customer_developer_experience.py +167 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/LICENSE +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/MANIFEST.in +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/contracts/openapi-routes.json +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/docs/native-experience-operations.md +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/examples/native_reflection_worker.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/exceptions.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/execution.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/experience.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/openai_reflection.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/reflection_worker.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix/workflow.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix.egg-info/dependency_links.txt +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix.egg-info/entry_points.txt +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix.egg-info/requires.txt +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/hebbrix.egg-info/top_level.txt +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/setup.cfg +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_advanced_resources.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_evidence_loop_resource.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_evidence_safety_boundary.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_execution_permission.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_experience_request.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_experience_workflow.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_followup_helpers.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_memories_resource.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_openai_reflection.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_openapi_parity.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_outcome_advice_resource.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_procedural_resource.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_reflection_worker_cli.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_release_version.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_sync_client.py +0 -0
- {hebbrix-2.6.1 → hebbrix-2.6.3}/tests/test_workflow_route_contract.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.6.3 — 2026-10-14 (candidate memory_ids)
|
|
4
|
+
|
|
5
|
+
- Candidates may carry optional `memory_ids` (at most 50 ids of 1-255 characters) naming the exact memories that action applies; when the candidate becomes the decision's action, its outcome is credited to those memories.
|
|
6
|
+
- The advisor input snapshot (`decide_with_advice`) admits and validates `memory_ids` before any evidence read, callback or write; `proofloop.decide` documents the candidate shape.
|
|
7
|
+
- Requires the server release that credits outcomes only to memories bound to the action taken; a `proof_context` attests what was retrieved and no longer earns per-memory outcome credit by itself.
|
|
8
|
+
|
|
9
|
+
## 2.6.2 — 2026-10-06 (compact advice, batches and confirmation)
|
|
10
|
+
|
|
11
|
+
- Correct canonical documentation metadata and simplify the stable three-call guide.
|
|
12
|
+
- Add optional compact search/advice, bounded independently committed decision/outcome batches, and explicit caller-confirmation transports.
|
|
13
|
+
- Add bounded chat-learning wait options while preserving the original job receipt.
|
|
14
|
+
- Keep historical confidence scope aliases, ACT-as-advice and protected outcome boundaries intact.
|
|
15
|
+
- Requires matching Round9 server routes; no benchmark superiority, latency SLA or automatic execution is implied.
|
|
16
|
+
|
|
3
17
|
## 2.6.1 — 2026-10-04 (advisory horizon helpers)
|
|
4
18
|
|
|
5
19
|
- Carry optional remaining_decisions and max_pilot_decisions through evidence reads and the once-only advisor callback.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hebbrix
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.3
|
|
4
4
|
Summary: Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs
|
|
5
5
|
Author-email: Hebbrix Team <support@hebbrix.com>
|
|
6
6
|
Maintainer-email: Hebbrix Team <support@hebbrix.com>
|
|
@@ -27,7 +27,7 @@ License: MIT License
|
|
|
27
27
|
SOFTWARE.
|
|
28
28
|
|
|
29
29
|
Project-URL: Homepage, https://hebbrix.com
|
|
30
|
-
Project-URL: Documentation, https://
|
|
30
|
+
Project-URL: Documentation, https://hebbrix.com/docs
|
|
31
31
|
Project-URL: Source, https://github.com/Hebbrix/hebbrix-python
|
|
32
32
|
Project-URL: Issues, https://github.com/Hebbrix/hebbrix-python/issues
|
|
33
33
|
Project-URL: Support, https://www.hebbrix.com/contact
|
|
@@ -65,54 +65,23 @@ Dynamic: license-file
|
|
|
65
65
|
|
|
66
66
|
Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs.
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
an action still requires independent permission.
|
|
68
|
+
The current stable package is **2.6.3**. Start with memory storage and search, or
|
|
69
|
+
the three-call outcome-learning workflow below. Advanced evidence and execution
|
|
70
|
+
permission transports are opt-in; installing the SDK never permits an action.
|
|
72
71
|
|
|
73
72
|
## Install
|
|
74
73
|
|
|
75
74
|
```bash
|
|
76
|
-
pip install hebbrix==2.6.
|
|
75
|
+
pip install hebbrix==2.6.3
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
Python 3.8+ is supported. `MemoryClient` is asynchronous. `SyncMemoryClient`
|
|
80
79
|
supports the core collection, memory, search, correction, procedure, and
|
|
81
|
-
|
|
80
|
+
outcome-learning workflows; advanced temporal, working-memory, consolidation,
|
|
82
81
|
memory-tool, and RL resources are currently async-only.
|
|
83
82
|
|
|
84
|
-
The runtime requires `httpx>=0.25.0,<1`; incompatible 1.x prereleases are excluded.
|
|
85
|
-
For the matching Round 5 backend, `setup_policy` accepts explicit `configuration`
|
|
86
|
-
options for versioned change response and declared optional-field sharing, plus
|
|
87
|
-
`value_objective={"success_value":10,"max_cost":20,"cost_unit":"USD"}`.
|
|
88
|
-
Report both actual success and cost with `record_outcome`. Chat follow-up capture
|
|
89
|
-
requires `features.learning: true` and an exact `outcome_followup.decision_id`;
|
|
90
|
-
captured signals are provisional, not verified execution or autonomy evidence.
|
|
91
|
-
These options require the matching runtime, not only the unchanged database schema.
|
|
92
|
-
|
|
93
83
|
## Quick start
|
|
94
84
|
|
|
95
|
-
October 2 follow-up: `proofloop.setup_policy` atomically creates a new
|
|
96
|
-
context/schema policy with explicitly declared low-risk exploration; existing
|
|
97
|
-
policies are not migrated automatically. `learning_report` reads a bounded,
|
|
98
|
-
scoped descriptive report, not proven uplift. `decide_with_advice` reads an
|
|
99
|
-
evidence card, invokes the supplied advisor once and logs its actual choice and
|
|
100
|
-
probabilities. `decide` accepts bounded `prior_action` / `prior_strength` for one
|
|
101
|
-
server-selected decision; this is not outcome evidence. These new helpers and
|
|
102
|
-
structured paraphrase matching require the matching October 2 outcome-followup
|
|
103
|
-
backend, not merely its database schema; inspect `/v1/release` before use.
|
|
104
|
-
Nothing here grants permission to execute. Learning performance and reliable
|
|
105
|
-
model compliance with feedback are not established.
|
|
106
|
-
|
|
107
|
-
Both clients expose `proofloop.register_context_schema`, `context_schema`,
|
|
108
|
-
`configure_policy`, `policy_configuration`, `policy_advice` and `action_advice`.
|
|
109
|
-
Enroll context before recording decisions. Configuration uses `expected_revision`
|
|
110
|
-
for compare-and-swap; do not retry a conflict blindly. Exploration remains an
|
|
111
|
-
explicit low-risk opt-in. `action_advice` takes the exact configured description,
|
|
112
|
-
policy/action IDs and context, and maps `user_id` to the confidence endpoint's
|
|
113
|
-
`end_user_id`. For the complete request shapes, see the
|
|
114
|
-
[learning guide](https://www.hebbrix.com/docs/learning).
|
|
115
|
-
|
|
116
85
|
```python
|
|
117
86
|
import asyncio
|
|
118
87
|
from hebbrix import MemoryClient
|
|
@@ -135,6 +104,62 @@ async def main():
|
|
|
135
104
|
asyncio.run(main())
|
|
136
105
|
```
|
|
137
106
|
|
|
107
|
+
## Learn from outcomes in three calls
|
|
108
|
+
|
|
109
|
+
Use server-side selection when Hebbrix should choose. Read-only advice is for a
|
|
110
|
+
caller that intentionally chooses outside Hebbrix; an LLM can ignore that advice.
|
|
111
|
+
Configure a new policy once, request a decision, then report its actual result:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
await client.proofloop.setup_policy(
|
|
115
|
+
"support.reply.v1", user_id="customer-42",
|
|
116
|
+
context_schema={"version": "v1", "fields": {
|
|
117
|
+
"issue": {"values": ["delivery", "billing"], "required": True}
|
|
118
|
+
}},
|
|
119
|
+
actions={
|
|
120
|
+
"explain": {"description": "Explain the delivery status", "target": "ticket",
|
|
121
|
+
"risk_tier": "low", "exploration_allowed": True},
|
|
122
|
+
"review": {"description": "Request a support review", "target": "ticket",
|
|
123
|
+
"risk_tier": "low", "exploration_allowed": True},
|
|
124
|
+
},
|
|
125
|
+
configuration={"strategy": "posterior_sampling"},
|
|
126
|
+
)
|
|
127
|
+
decision = await client.proofloop.decide(
|
|
128
|
+
policy_key="support.reply.v1", user_id="customer-42", mode="auto",
|
|
129
|
+
context={"issue": "delivery"},
|
|
130
|
+
candidates=[{"action_key": "explain"}, {"action_key": "review"}],
|
|
131
|
+
idempotency_key="ticket-42-decision",
|
|
132
|
+
)
|
|
133
|
+
# Your application checks permission and performs the action separately.
|
|
134
|
+
# Here success is the actual result supplied by that application, not a prediction.
|
|
135
|
+
await client.proofloop.record_outcome(
|
|
136
|
+
decision["decision_id"], success=success,
|
|
137
|
+
idempotency_key="ticket-42-result",
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`success` must come from your application or an independently authorized
|
|
142
|
+
verifier. Do not report the recommendation itself as a successful execution.
|
|
143
|
+
Keep action identities and required context stable. Use a new policy/version
|
|
144
|
+
when changing what an action or outcome means. See the
|
|
145
|
+
[recommended defaults](https://hebbrix.com/docs/learning).
|
|
146
|
+
|
|
147
|
+
## Advice and integration boundaries
|
|
148
|
+
|
|
149
|
+
`proofloop.action_advice(...)` reads the exact configured action and context.
|
|
150
|
+
The canonical `gate` is `ASK`, `REVIEW`, `ACT`, or `BLOCK`. `BLOCK` dominates;
|
|
151
|
+
`ACT` is advice, not permission. Apply your own current authorization and human
|
|
152
|
+
approval policy before executing any tool. Do not infer permission from a score.
|
|
153
|
+
|
|
154
|
+
Version 2.6.3 lets each `proofloop.decide` candidate carry `memory_ids`: the exact
|
|
155
|
+
memories that action applies. When that candidate becomes the decision's action,
|
|
156
|
+
its outcome is credited to those memories; a `proof_context` attests what was
|
|
157
|
+
retrieved but never earns per-memory outcome credit by itself.
|
|
158
|
+
|
|
159
|
+
Version 2.6.2 adds compact advice, batch, and explicit confirmation helpers.
|
|
160
|
+
They require matching Round9 server routes. Compact views retain scope and safety
|
|
161
|
+
caveats; complete receipts remain on the server.
|
|
162
|
+
|
|
138
163
|
## Durable readiness
|
|
139
164
|
|
|
140
165
|
Memory writes return either a searchable completion or a durable `202` receipt.
|
|
@@ -215,7 +240,7 @@ The production API publishes exact build and artifact compatibility at
|
|
|
215
240
|
[`GET /v1/release`](https://api.hebbrix.com/v1/release). The public OpenAPI is
|
|
216
241
|
[`/openapi.json`](https://api.hebbrix.com/openapi.json).
|
|
217
242
|
|
|
218
|
-
- [Documentation](https://
|
|
243
|
+
- [Documentation](https://hebbrix.com/docs)
|
|
219
244
|
- [API reference](https://api.hebbrix.com/docs)
|
|
220
245
|
- [PyPI files](https://pypi.org/project/hebbrix/#files)
|
|
221
246
|
- [Support](https://www.hebbrix.com/contact)
|
|
@@ -223,14 +248,25 @@ The production API publishes exact build and artifact compatibility at
|
|
|
223
248
|
## License
|
|
224
249
|
|
|
225
250
|
MIT. See `LICENSE` in the distribution.
|
|
226
|
-
##
|
|
251
|
+
## Advanced evidence workflows
|
|
227
252
|
|
|
228
253
|
The current source includes `client.experiences`, bounded reflection workers,
|
|
229
254
|
separate lesson review/revision and explicit one-use execution admission. These
|
|
230
|
-
methods require the
|
|
231
|
-
|
|
255
|
+
methods require the server's published compatibility contract and separately
|
|
256
|
+
scoped credentials. The package supplies `hebbrix-reflect --help`.
|
|
232
257
|
Importing it does not call a model, approve a lesson or execute a tool.
|
|
233
258
|
|
|
234
|
-
See
|
|
259
|
+
See the [documentation](https://hebbrix.com/docs) for role scopes,
|
|
235
260
|
uncertain-call recovery, exact-request binding and policy rollback. Do not treat a
|
|
236
261
|
lesson, score, review or issued permit as execution permission.
|
|
262
|
+
|
|
263
|
+
## Stability
|
|
264
|
+
|
|
265
|
+
Stable SDK versions follow semantic versioning. Patch updates correct defects;
|
|
266
|
+
new optional fields and methods are additive. Existing required context, action
|
|
267
|
+
identity, owner scope, and historical outcomes are not silently rewritten.
|
|
268
|
+
Experimental APIs are marked separately. Security and correctness guards may
|
|
269
|
+
be tightened immediately; migrations and other incompatible changes must be
|
|
270
|
+
documented with their supported replacement. Read [CHANGELOG.md](CHANGELOG.md)
|
|
271
|
+
before upgrading and pin versions in production. Release cadence is not a
|
|
272
|
+
performance, compliance, or reliability guarantee.
|
|
@@ -2,54 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
Typed Python client for Hebbrix memory, retrieval, and outcome-learning APIs.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
an action still requires independent permission.
|
|
5
|
+
The current stable package is **2.6.3**. Start with memory storage and search, or
|
|
6
|
+
the three-call outcome-learning workflow below. Advanced evidence and execution
|
|
7
|
+
permission transports are opt-in; installing the SDK never permits an action.
|
|
9
8
|
|
|
10
9
|
## Install
|
|
11
10
|
|
|
12
11
|
```bash
|
|
13
|
-
pip install hebbrix==2.6.
|
|
12
|
+
pip install hebbrix==2.6.3
|
|
14
13
|
```
|
|
15
14
|
|
|
16
15
|
Python 3.8+ is supported. `MemoryClient` is asynchronous. `SyncMemoryClient`
|
|
17
16
|
supports the core collection, memory, search, correction, procedure, and
|
|
18
|
-
|
|
17
|
+
outcome-learning workflows; advanced temporal, working-memory, consolidation,
|
|
19
18
|
memory-tool, and RL resources are currently async-only.
|
|
20
19
|
|
|
21
|
-
The runtime requires `httpx>=0.25.0,<1`; incompatible 1.x prereleases are excluded.
|
|
22
|
-
For the matching Round 5 backend, `setup_policy` accepts explicit `configuration`
|
|
23
|
-
options for versioned change response and declared optional-field sharing, plus
|
|
24
|
-
`value_objective={"success_value":10,"max_cost":20,"cost_unit":"USD"}`.
|
|
25
|
-
Report both actual success and cost with `record_outcome`. Chat follow-up capture
|
|
26
|
-
requires `features.learning: true` and an exact `outcome_followup.decision_id`;
|
|
27
|
-
captured signals are provisional, not verified execution or autonomy evidence.
|
|
28
|
-
These options require the matching runtime, not only the unchanged database schema.
|
|
29
|
-
|
|
30
20
|
## Quick start
|
|
31
21
|
|
|
32
|
-
October 2 follow-up: `proofloop.setup_policy` atomically creates a new
|
|
33
|
-
context/schema policy with explicitly declared low-risk exploration; existing
|
|
34
|
-
policies are not migrated automatically. `learning_report` reads a bounded,
|
|
35
|
-
scoped descriptive report, not proven uplift. `decide_with_advice` reads an
|
|
36
|
-
evidence card, invokes the supplied advisor once and logs its actual choice and
|
|
37
|
-
probabilities. `decide` accepts bounded `prior_action` / `prior_strength` for one
|
|
38
|
-
server-selected decision; this is not outcome evidence. These new helpers and
|
|
39
|
-
structured paraphrase matching require the matching October 2 outcome-followup
|
|
40
|
-
backend, not merely its database schema; inspect `/v1/release` before use.
|
|
41
|
-
Nothing here grants permission to execute. Learning performance and reliable
|
|
42
|
-
model compliance with feedback are not established.
|
|
43
|
-
|
|
44
|
-
Both clients expose `proofloop.register_context_schema`, `context_schema`,
|
|
45
|
-
`configure_policy`, `policy_configuration`, `policy_advice` and `action_advice`.
|
|
46
|
-
Enroll context before recording decisions. Configuration uses `expected_revision`
|
|
47
|
-
for compare-and-swap; do not retry a conflict blindly. Exploration remains an
|
|
48
|
-
explicit low-risk opt-in. `action_advice` takes the exact configured description,
|
|
49
|
-
policy/action IDs and context, and maps `user_id` to the confidence endpoint's
|
|
50
|
-
`end_user_id`. For the complete request shapes, see the
|
|
51
|
-
[learning guide](https://www.hebbrix.com/docs/learning).
|
|
52
|
-
|
|
53
22
|
```python
|
|
54
23
|
import asyncio
|
|
55
24
|
from hebbrix import MemoryClient
|
|
@@ -72,6 +41,62 @@ async def main():
|
|
|
72
41
|
asyncio.run(main())
|
|
73
42
|
```
|
|
74
43
|
|
|
44
|
+
## Learn from outcomes in three calls
|
|
45
|
+
|
|
46
|
+
Use server-side selection when Hebbrix should choose. Read-only advice is for a
|
|
47
|
+
caller that intentionally chooses outside Hebbrix; an LLM can ignore that advice.
|
|
48
|
+
Configure a new policy once, request a decision, then report its actual result:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
await client.proofloop.setup_policy(
|
|
52
|
+
"support.reply.v1", user_id="customer-42",
|
|
53
|
+
context_schema={"version": "v1", "fields": {
|
|
54
|
+
"issue": {"values": ["delivery", "billing"], "required": True}
|
|
55
|
+
}},
|
|
56
|
+
actions={
|
|
57
|
+
"explain": {"description": "Explain the delivery status", "target": "ticket",
|
|
58
|
+
"risk_tier": "low", "exploration_allowed": True},
|
|
59
|
+
"review": {"description": "Request a support review", "target": "ticket",
|
|
60
|
+
"risk_tier": "low", "exploration_allowed": True},
|
|
61
|
+
},
|
|
62
|
+
configuration={"strategy": "posterior_sampling"},
|
|
63
|
+
)
|
|
64
|
+
decision = await client.proofloop.decide(
|
|
65
|
+
policy_key="support.reply.v1", user_id="customer-42", mode="auto",
|
|
66
|
+
context={"issue": "delivery"},
|
|
67
|
+
candidates=[{"action_key": "explain"}, {"action_key": "review"}],
|
|
68
|
+
idempotency_key="ticket-42-decision",
|
|
69
|
+
)
|
|
70
|
+
# Your application checks permission and performs the action separately.
|
|
71
|
+
# Here success is the actual result supplied by that application, not a prediction.
|
|
72
|
+
await client.proofloop.record_outcome(
|
|
73
|
+
decision["decision_id"], success=success,
|
|
74
|
+
idempotency_key="ticket-42-result",
|
|
75
|
+
)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`success` must come from your application or an independently authorized
|
|
79
|
+
verifier. Do not report the recommendation itself as a successful execution.
|
|
80
|
+
Keep action identities and required context stable. Use a new policy/version
|
|
81
|
+
when changing what an action or outcome means. See the
|
|
82
|
+
[recommended defaults](https://hebbrix.com/docs/learning).
|
|
83
|
+
|
|
84
|
+
## Advice and integration boundaries
|
|
85
|
+
|
|
86
|
+
`proofloop.action_advice(...)` reads the exact configured action and context.
|
|
87
|
+
The canonical `gate` is `ASK`, `REVIEW`, `ACT`, or `BLOCK`. `BLOCK` dominates;
|
|
88
|
+
`ACT` is advice, not permission. Apply your own current authorization and human
|
|
89
|
+
approval policy before executing any tool. Do not infer permission from a score.
|
|
90
|
+
|
|
91
|
+
Version 2.6.3 lets each `proofloop.decide` candidate carry `memory_ids`: the exact
|
|
92
|
+
memories that action applies. When that candidate becomes the decision's action,
|
|
93
|
+
its outcome is credited to those memories; a `proof_context` attests what was
|
|
94
|
+
retrieved but never earns per-memory outcome credit by itself.
|
|
95
|
+
|
|
96
|
+
Version 2.6.2 adds compact advice, batch, and explicit confirmation helpers.
|
|
97
|
+
They require matching Round9 server routes. Compact views retain scope and safety
|
|
98
|
+
caveats; complete receipts remain on the server.
|
|
99
|
+
|
|
75
100
|
## Durable readiness
|
|
76
101
|
|
|
77
102
|
Memory writes return either a searchable completion or a durable `202` receipt.
|
|
@@ -152,7 +177,7 @@ The production API publishes exact build and artifact compatibility at
|
|
|
152
177
|
[`GET /v1/release`](https://api.hebbrix.com/v1/release). The public OpenAPI is
|
|
153
178
|
[`/openapi.json`](https://api.hebbrix.com/openapi.json).
|
|
154
179
|
|
|
155
|
-
- [Documentation](https://
|
|
180
|
+
- [Documentation](https://hebbrix.com/docs)
|
|
156
181
|
- [API reference](https://api.hebbrix.com/docs)
|
|
157
182
|
- [PyPI files](https://pypi.org/project/hebbrix/#files)
|
|
158
183
|
- [Support](https://www.hebbrix.com/contact)
|
|
@@ -160,14 +185,25 @@ The production API publishes exact build and artifact compatibility at
|
|
|
160
185
|
## License
|
|
161
186
|
|
|
162
187
|
MIT. See `LICENSE` in the distribution.
|
|
163
|
-
##
|
|
188
|
+
## Advanced evidence workflows
|
|
164
189
|
|
|
165
190
|
The current source includes `client.experiences`, bounded reflection workers,
|
|
166
191
|
separate lesson review/revision and explicit one-use execution admission. These
|
|
167
|
-
methods require the
|
|
168
|
-
|
|
192
|
+
methods require the server's published compatibility contract and separately
|
|
193
|
+
scoped credentials. The package supplies `hebbrix-reflect --help`.
|
|
169
194
|
Importing it does not call a model, approve a lesson or execute a tool.
|
|
170
195
|
|
|
171
|
-
See
|
|
196
|
+
See the [documentation](https://hebbrix.com/docs) for role scopes,
|
|
172
197
|
uncertain-call recovery, exact-request binding and policy rollback. Do not treat a
|
|
173
198
|
lesson, score, review or issued permit as execution permission.
|
|
199
|
+
|
|
200
|
+
## Stability
|
|
201
|
+
|
|
202
|
+
Stable SDK versions follow semantic versioning. Patch updates correct defects;
|
|
203
|
+
new optional fields and methods are additive. Existing required context, action
|
|
204
|
+
identity, owner scope, and historical outcomes are not silently rewritten.
|
|
205
|
+
Experimental APIs are marked separately. Security and correctness guards may
|
|
206
|
+
be tightened immediately; migrations and other incompatible changes must be
|
|
207
|
+
documented with their supported replacement. Read [CHANGELOG.md](CHANGELOG.md)
|
|
208
|
+
before upgrading and pin versions in production. Release cadence is not a
|
|
209
|
+
performance, compliance, or reliability guarantee.
|
|
@@ -5,7 +5,7 @@ production OpenAPI and ``GET /v1/users/me/capabilities``. The experimental
|
|
|
5
5
|
World Model is intentionally absent from this release.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "2.6.
|
|
8
|
+
__version__ = "2.6.3"
|
|
9
9
|
__author__ = "Hebbrix Team"
|
|
10
10
|
__license__ = "MIT"
|
|
11
11
|
|
|
@@ -21,7 +21,7 @@ from hebbrix.exceptions import (
|
|
|
21
21
|
ServerError,
|
|
22
22
|
ValidationError,
|
|
23
23
|
)
|
|
24
|
-
from hebbrix.models import EvidenceClaim, GroundingReceipt, SearchSafetyEnvelope
|
|
24
|
+
from hebbrix.models import ActionAdviceReceipt, EvidenceClaim, GroundingReceipt, SearchSafetyEnvelope
|
|
25
25
|
from hebbrix.sync_client import SyncMemoryClient
|
|
26
26
|
|
|
27
27
|
__all__ = [
|
|
@@ -39,4 +39,5 @@ __all__ = [
|
|
|
39
39
|
"GroundingReceipt",
|
|
40
40
|
"EvidenceClaim",
|
|
41
41
|
"SearchSafetyEnvelope",
|
|
42
|
+
"ActionAdviceReceipt",
|
|
42
43
|
]
|
|
@@ -5,6 +5,54 @@ import math
|
|
|
5
5
|
import re
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
def _validate_advice_view(view):
|
|
9
|
+
if view is not None and view not in ("full", "compact"):
|
|
10
|
+
raise ValueError("view must be full or compact")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _confirmation_payload(observation_id, idempotency_key, success, confirmed,
|
|
14
|
+
collection_id=None, user_id=None, source_system=None,
|
|
15
|
+
source_event_id=None, evidence_digest=None):
|
|
16
|
+
if type(success) is not bool or confirmed is not True:
|
|
17
|
+
raise ValueError("explicit Boolean success and confirmed=True are required")
|
|
18
|
+
for field, value in (("observation_id", observation_id),
|
|
19
|
+
("idempotency_key", idempotency_key)):
|
|
20
|
+
if type(value) is not str or not value.strip() or len(value) > 160:
|
|
21
|
+
raise ValueError("{} must be a nonempty bounded string".format(field))
|
|
22
|
+
return {key: value for key, value in dict(
|
|
23
|
+
observation_id=observation_id, idempotency_key=idempotency_key,
|
|
24
|
+
success=success, confirmed=True, collection_id=collection_id, user_id=user_id,
|
|
25
|
+
source_system=source_system, source_event_id=source_event_id,
|
|
26
|
+
evidence_digest=evidence_digest,
|
|
27
|
+
).items() if value is not None}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _batch_payload(items, view="compact", outcomes=False):
|
|
31
|
+
_validate_advice_view(view)
|
|
32
|
+
if type(items) is not list or not 1 <= len(items) <= 50:
|
|
33
|
+
raise ValueError("batch items must contain 1-50 requests")
|
|
34
|
+
copied = _json_snapshot(items, "batch items", 4_000_000)
|
|
35
|
+
for item in copied:
|
|
36
|
+
if type(item) is not dict:
|
|
37
|
+
raise ValueError("each batch item must be an object")
|
|
38
|
+
key = item.get("idempotency_key")
|
|
39
|
+
if type(key) is not str or not key.strip() or len(key) > 160:
|
|
40
|
+
raise ValueError("each batch item needs a nonempty idempotency_key")
|
|
41
|
+
if outcomes and (type(item.get("decision_id")) is not str or
|
|
42
|
+
not item["decision_id"].strip() or
|
|
43
|
+
type(item.get("outcome")) is not dict):
|
|
44
|
+
raise ValueError("outcome items need decision_id and an outcome object")
|
|
45
|
+
if not outcomes and "proof_context" in item:
|
|
46
|
+
context = item.pop("proof_context")
|
|
47
|
+
token = context.get("token") if type(context) is dict else context
|
|
48
|
+
if type(token) is not str or not token.strip():
|
|
49
|
+
raise ValueError("proof_context must contain the original proof token")
|
|
50
|
+
if "proof_context_token" in item and item["proof_context_token"] != token:
|
|
51
|
+
raise ValueError("conflicting proof context tokens")
|
|
52
|
+
item["proof_context_token"] = token
|
|
53
|
+
return {"items": copied, **({"view": view} if view is not None else {})}
|
|
54
|
+
|
|
55
|
+
|
|
8
56
|
def _validate_advisor_horizon(remaining_decisions, max_pilot_decisions):
|
|
9
57
|
for field, value, maximum in (("remaining_decisions", remaining_decisions, 10000),
|
|
10
58
|
("max_pilot_decisions", max_pilot_decisions, 8)):
|
|
@@ -73,9 +121,11 @@ def _snapshot_advisor_inputs(candidates, context):
|
|
|
73
121
|
"action_key",
|
|
74
122
|
"description",
|
|
75
123
|
"features",
|
|
124
|
+
"memory_ids",
|
|
76
125
|
}:
|
|
77
126
|
raise ValueError(
|
|
78
|
-
"candidates must contain only action_key, description
|
|
127
|
+
"candidates must contain only action_key, description, features "
|
|
128
|
+
"and memory_ids"
|
|
79
129
|
)
|
|
80
130
|
key = candidate.get("action_key")
|
|
81
131
|
if (
|
|
@@ -97,6 +147,18 @@ def _snapshot_advisor_inputs(candidates, context):
|
|
|
97
147
|
)
|
|
98
148
|
if "features" in candidate and type(candidate["features"]) is not dict:
|
|
99
149
|
raise ValueError("candidate features must be a JSON object")
|
|
150
|
+
memory_ids = candidate.get("memory_ids")
|
|
151
|
+
if memory_ids is not None and (
|
|
152
|
+
type(memory_ids) is not list
|
|
153
|
+
or len(memory_ids) > 50
|
|
154
|
+
or any(
|
|
155
|
+
type(memory_id) is not str or not 1 <= len(memory_id) <= 255
|
|
156
|
+
for memory_id in memory_ids
|
|
157
|
+
)
|
|
158
|
+
):
|
|
159
|
+
raise ValueError(
|
|
160
|
+
"candidate memory_ids must be a list of at most 50 memory ids"
|
|
161
|
+
)
|
|
100
162
|
keys.append(key)
|
|
101
163
|
return candidates_copy, context_copy, keys
|
|
102
164
|
|
|
@@ -11,11 +11,27 @@ Example:
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from typing import Any, Dict, List, Optional
|
|
14
|
+
import math
|
|
14
15
|
|
|
15
16
|
import requests
|
|
16
17
|
from hebbrix.client import MemoryClient
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _chat_readiness_options(wait_for_learning_seconds, include_low_confidence):
|
|
21
|
+
if (isinstance(wait_for_learning_seconds, bool) or
|
|
22
|
+
not isinstance(wait_for_learning_seconds, (int, float)) or
|
|
23
|
+
not math.isfinite(wait_for_learning_seconds) or
|
|
24
|
+
not 0 <= wait_for_learning_seconds <= 20):
|
|
25
|
+
raise ValueError("wait_for_learning_seconds must be between 0 and 20")
|
|
26
|
+
if type(include_low_confidence) is not bool:
|
|
27
|
+
raise ValueError("include_low_confidence must be explicitly Boolean")
|
|
28
|
+
return {
|
|
29
|
+
**({"wait_for_learning_seconds": wait_for_learning_seconds}
|
|
30
|
+
if wait_for_learning_seconds else {}),
|
|
31
|
+
**({"include_low_confidence": True} if include_low_confidence else {}),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
19
35
|
class MemoryChat:
|
|
20
36
|
"""
|
|
21
37
|
Simple chat interface with automatic memory integration.
|
|
@@ -94,6 +110,8 @@ class MemoryChat:
|
|
|
94
110
|
session_id: str,
|
|
95
111
|
temperature: float = 0.7,
|
|
96
112
|
max_tokens: Optional[int] = None,
|
|
113
|
+
*, wait_for_learning_seconds: float = 0,
|
|
114
|
+
include_low_confidence: bool = False,
|
|
97
115
|
) -> str:
|
|
98
116
|
"""
|
|
99
117
|
Send a message and get a response with automatic memory integration.
|
|
@@ -122,6 +140,7 @@ class MemoryChat:
|
|
|
122
140
|
"prompt_strategy": self.prompt_strategy,
|
|
123
141
|
"memory_limit": self.memory_limit,
|
|
124
142
|
"temperature": temperature,
|
|
143
|
+
**_chat_readiness_options(wait_for_learning_seconds, include_low_confidence),
|
|
125
144
|
}
|
|
126
145
|
|
|
127
146
|
if max_tokens:
|
|
@@ -146,6 +165,8 @@ class MemoryChat:
|
|
|
146
165
|
session_id: str,
|
|
147
166
|
temperature: float = 0.7,
|
|
148
167
|
max_tokens: Optional[int] = None,
|
|
168
|
+
*, wait_for_learning_seconds: float = 0,
|
|
169
|
+
include_low_confidence: bool = False,
|
|
149
170
|
) -> Dict[str, Any]:
|
|
150
171
|
"""
|
|
151
172
|
Send a message and get full response with memory context.
|
|
@@ -176,6 +197,7 @@ class MemoryChat:
|
|
|
176
197
|
"prompt_strategy": self.prompt_strategy,
|
|
177
198
|
"memory_limit": self.memory_limit,
|
|
178
199
|
"temperature": temperature,
|
|
200
|
+
**_chat_readiness_options(wait_for_learning_seconds, include_low_confidence),
|
|
179
201
|
}
|
|
180
202
|
|
|
181
203
|
if max_tokens:
|
|
@@ -93,7 +93,7 @@ class MemoryClient:
|
|
|
93
93
|
"""Get request headers."""
|
|
94
94
|
headers = {
|
|
95
95
|
"Content-Type": "application/json",
|
|
96
|
-
"User-Agent": "hebbrix-python/2.6.
|
|
96
|
+
"User-Agent": "hebbrix-python/2.6.3",
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
if self.api_key:
|
|
@@ -254,6 +254,7 @@ class MemoryClient:
|
|
|
254
254
|
include_low_confidence: bool = False,
|
|
255
255
|
group_by_source: bool = True,
|
|
256
256
|
debug: bool = False,
|
|
257
|
+
view: Optional[str] = None,
|
|
257
258
|
) -> List[Dict[str, Any]]:
|
|
258
259
|
"""
|
|
259
260
|
Search memories.
|
|
@@ -282,6 +283,7 @@ class MemoryClient:
|
|
|
282
283
|
include_low_confidence=include_low_confidence,
|
|
283
284
|
group_by_source=group_by_source,
|
|
284
285
|
debug=debug,
|
|
286
|
+
view=view,
|
|
285
287
|
)
|
|
286
288
|
|
|
287
289
|
async def search_with_proof(
|
|
@@ -299,6 +301,7 @@ class MemoryClient:
|
|
|
299
301
|
include_low_confidence: bool = False,
|
|
300
302
|
group_by_source: bool = True,
|
|
301
303
|
debug: bool = False,
|
|
304
|
+
view: Optional[str] = None,
|
|
302
305
|
) -> Dict[str, Any]:
|
|
303
306
|
"""Search and return both results and the automatic ProofLoop context."""
|
|
304
307
|
|
|
@@ -316,6 +319,7 @@ class MemoryClient:
|
|
|
316
319
|
include_low_confidence=include_low_confidence,
|
|
317
320
|
group_by_source=group_by_source,
|
|
318
321
|
debug=debug,
|
|
322
|
+
view=view,
|
|
319
323
|
)
|
|
320
324
|
|
|
321
325
|
async def reason(
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
"""Public response contracts for evidence-bearing Hebbrix operations."""
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict, List, TypedDict
|
|
3
|
+
from typing import Any, Dict, List, TypedDict, Literal, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ActionAdviceReceipt(TypedDict, total=False):
|
|
7
|
+
"""Canonical advice envelope. ACT is never execution authorization."""
|
|
8
|
+
|
|
9
|
+
gate: Literal["ASK", "REVIEW", "ACT", "BLOCK"]
|
|
10
|
+
recommendation: str
|
|
11
|
+
recommended_action: str
|
|
12
|
+
action_confidence: Optional[float]
|
|
13
|
+
blocked_by: Optional[str]
|
|
14
|
+
blocked_hint: Optional[str]
|
|
15
|
+
autonomy_evidence: Dict[str, Any]
|
|
16
|
+
action_evidence: List[Dict[str, Any]]
|
|
17
|
+
authorization_granted: bool
|
|
18
|
+
execution_permission_required: bool
|
|
4
19
|
|
|
5
20
|
|
|
6
21
|
class GroundingReceipt(TypedDict, total=False):
|