hexgate 0.2.1__tar.gz → 0.2.2__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.
- hexgate-0.2.2/LICENSE +21 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/PKG-INFO +74 -39
- {hexgate-0.2.1 → hexgate-0.2.2}/README.md +70 -38
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/google/runner.py +18 -2
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/openai/runner.py +10 -9
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/PKG-INFO +74 -39
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/SOURCES.txt +1 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/pyproject.toml +3 -1
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/google/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/google/tools.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/google/wrapper.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/langchain/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/langchain/agent.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/langchain/tools.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/langchain/wrapper.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/openai/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/openai/tools.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/openai/wrapper.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/pydantic_ai/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/pydantic_ai/agent.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/pydantic_ai/tools.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/adapters/pydantic_ai/wrapper.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/builtin/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/builtin/researcher/agent.yaml +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/builtin/researcher/policy.yaml +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/builtin/researcher/system.md +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/factory.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/loader.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/models.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/agents/prompts/agent_system.md +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/audit.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/bootstrap.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/_common.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/chat.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/policy/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/policy/main.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/google.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/hexgate.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/langchain.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/main.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/manifest.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/models.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/openai.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/pydantic_ai.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/register/register.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/serve.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cli/state.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cloud/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cloud/attenuate.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cloud/biscuit.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/cloud/client.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/config/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/config/settings.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/command_policy.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/context.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/sandbox_runtime.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/srt.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/runtime/workspace.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/binding.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/bundle.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/constraints.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/decision.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/enforcer.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/errors.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/file_scope.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/models.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/policy.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/policy_set.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/rego.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/rego_wasm.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/signing.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/source.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/security/wasm_engine.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/streaming/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/streaming/events.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/streaming/normalize.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/bash.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/decorators.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/fetch.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/_common.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/edit_file.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/glob.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/grep.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/read_file.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/files/write_file.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/refund.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tools/websearch.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tracing/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/tracing/langfuse.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/utils/__init__.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate/utils/retry.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/dependency_links.txt +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/entry_points.txt +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/requires.txt +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/hexgate.egg-info/top_level.txt +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/setup.cfg +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/tests/test_bootstrap.py +0 -0
- {hexgate-0.2.1 → hexgate-0.2.2}/tests/test_demo.py +0 -0
hexgate-0.2.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hexamind
|
|
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.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexgate
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: HexaGate — authorization infrastructure for AI agents (agent runtime + cloud client).
|
|
5
|
+
License-Expression: MIT
|
|
5
6
|
Requires-Python: >=3.13
|
|
6
7
|
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
7
9
|
Requires-Dist: bashlex>=0.18
|
|
8
10
|
Requires-Dist: biscuit-python>=0.4
|
|
9
11
|
Requires-Dist: cryptography>=42
|
|
@@ -33,21 +35,77 @@ Requires-Dist: jupyter; extra == "dev"
|
|
|
33
35
|
Requires-Dist: pytest>=8.4.1; extra == "dev"
|
|
34
36
|
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
35
37
|
Requires-Dist: ruff>=0.12.2; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
<div align="center">
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
# HexaGate
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
- `Linkup` web search
|
|
44
|
-
- Tavily-based page fetch
|
|
45
|
-
- `Langfuse` tracing
|
|
44
|
+
**Authorization infrastructure for AI agents.**
|
|
45
|
+
Policy enforcement, signed policy bundles, per-request user scope, audit trail — for OpenAI Agents, LangChain, Google ADK, Pydantic AI, or a native runtime.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
[](https://pypi.org/project/hexgate/)
|
|
48
|
+
[](https://pypi.org/project/hexgate/)
|
|
49
|
+
[](https://github.com/HexamindOrganisation/hexgate/actions/workflows/tests.yml)
|
|
50
|
+
[](https://pypi.org/project/hexgate/)
|
|
51
|
+
[](LICENSE)
|
|
48
52
|
|
|
49
|
-
-
|
|
50
|
-
|
|
53
|
+
[Quick Start](#-quick-start--local-cli) · [Two paths](#-which-path-do-i-pick) · [Framework adapters](#-framework-agent-wrapping) · [Policy bundles](#-policy-bundles--compile-sign-enforce-wasm) · [User scope](#-user-scope--roles) · [Platform](#-hexagate-platform)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## What is HexaGate?
|
|
60
|
+
|
|
61
|
+
HexaGate is two things that move together:
|
|
62
|
+
|
|
63
|
+
- **`hexgate` — the SDK.** A Python runtime that gates every tool call through a typed `Decision` (allow / deny / approval-required), wraps your existing OpenAI / LangChain / Google ADK / Pydantic AI agent without rewriting it, and threads per-request user identity through tracing + audit.
|
|
64
|
+
- **The HexaGate platform** *(optional)* — a FastAPI control plane + React dashboard for editing policy in a browser, minting per-project tokens, watching live decisions stream from a serving agent, and shipping signed WASM policy bundles to production.
|
|
65
|
+
|
|
66
|
+
You can use the SDK with nothing else (single-process REPL, YAML on disk). Or plug in the platform when you want auditable decisions in ClickHouse, a shared Playground UI, and live policy edits.
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
┌─────────────────────────────────────────┐
|
|
70
|
+
your code ───► │ create_agent / wrap_*_agent / Runner │
|
|
71
|
+
│ ↓ │
|
|
72
|
+
│ PolicyEnforcer.decide(role, tool) │
|
|
73
|
+
│ ↓ │
|
|
74
|
+
│ allow · deny · approval_required │
|
|
75
|
+
└────────────────────┬────────────────────┘
|
|
76
|
+
│
|
|
77
|
+
┌────────────────────────┼─────────────────────────┐
|
|
78
|
+
▼ ▼ ▼
|
|
79
|
+
┌────────────────┐ ┌──────────────────┐ ┌────────────────┐
|
|
80
|
+
│ Local policy │ │ Signed WASM │ │ Audit log │
|
|
81
|
+
│ (YAML / dir, │ │ bundle from │ │ (ClickHouse │
|
|
82
|
+
│ hot reload) │ │ HexaGate cloud │ │ via REST) │
|
|
83
|
+
└────────────────┘ └──────────────────┘ └────────────────┘
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Table of contents
|
|
87
|
+
|
|
88
|
+
- [Prerequisites](#-prerequisites)
|
|
89
|
+
- [Quick Start — Local CLI](#-quick-start--local-cli)
|
|
90
|
+
- [Which path do I pick?](#-which-path-do-i-pick) — chat vs serve
|
|
91
|
+
- [Quick Start — Platform](#-quick-start--platform)
|
|
92
|
+
- [Core primitives](#-core-primitives)
|
|
93
|
+
- [Build an agent — end to end](#-build-an-agent--end-to-end)
|
|
94
|
+
- [What you can import](#-what-you-can-import)
|
|
95
|
+
- [Framework agent wrapping](#-framework-agent-wrapping) — OpenAI, LangChain, Google ADK, Pydantic AI
|
|
96
|
+
- [Define agents in code](#-define-agents-in-code)
|
|
97
|
+
- [Builtin and local agents](#-builtin-and-local-agents)
|
|
98
|
+
- [Policy shape](#-policy-shape)
|
|
99
|
+
- [Tool-call policy enforcement](#-tool-call-policy-enforcement)
|
|
100
|
+
- [Policy bundles — compile, sign, enforce (WASM)](#-policy-bundles--compile-sign-enforce-wasm)
|
|
101
|
+
- [Approval-required tool calls](#-approval-required-tool-calls)
|
|
102
|
+
- [Workspace sandbox](#-workspace-sandbox)
|
|
103
|
+
- [Environment](#-environment)
|
|
104
|
+
- [Tests & dev tooling](#-tests--dev-tooling)
|
|
105
|
+
- [CLI reference](#-cli-reference)
|
|
106
|
+
- [HexaGate platform](#-hexagate-platform)
|
|
107
|
+
- [User scope + roles](#-user-scope--roles)
|
|
108
|
+
- [Stream results](#-stream-results)
|
|
51
109
|
|
|
52
110
|
## 🛠️ Prerequisites
|
|
53
111
|
|
|
@@ -1059,41 +1117,18 @@ The platform-side test suite is separate and lives at `platform/api/tests/`:
|
|
|
1059
1117
|
cd platform/api && uv run pytest tests/
|
|
1060
1118
|
```
|
|
1061
1119
|
|
|
1062
|
-
##
|
|
1063
|
-
|
|
1064
|
-
Install the package into your current environment:
|
|
1065
|
-
|
|
1066
|
-
```bash
|
|
1067
|
-
python -m pip install -e .
|
|
1068
|
-
```
|
|
1120
|
+
## 🖥️ CLI reference
|
|
1069
1121
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
```bash
|
|
1073
|
-
python examples/demo.py
|
|
1074
|
-
```
|
|
1075
|
-
|
|
1076
|
-
Run the inline chat CLI with a local or builtin YAML agent:
|
|
1077
|
-
|
|
1078
|
-
```bash
|
|
1079
|
-
hexgate chat --agent example_agent
|
|
1080
|
-
```
|
|
1081
|
-
|
|
1082
|
-
Run the CLI with code-defined agents from a Python script:
|
|
1122
|
+
The `hexgate` binary exposes `chat`, `serve`, `register`, and `policy` subcommands. The [Quick Start](#-quick-start--local-cli) covers `chat`; this section drills into `register` and `serve` for the platform path.
|
|
1083
1123
|
|
|
1084
1124
|
```bash
|
|
1125
|
+
hexgate --help # list subcommands
|
|
1126
|
+
hexgate <subcommand> --help # flags for a subcommand
|
|
1127
|
+
hexgate chat --list-agents # show resolvable agents
|
|
1085
1128
|
hexgate chat --use examples/file_agents.py --agent workspace_explorer
|
|
1086
|
-
hexgate chat --use examples/file_agents.py --agent repo_editor
|
|
1087
|
-
hexgate chat --use examples/research_agents.py --agent update_researcher
|
|
1088
1129
|
hexgate chat --use examples/research_agents.py --agent update_researcher --approval-mode ask
|
|
1089
1130
|
```
|
|
1090
1131
|
|
|
1091
|
-
List what the CLI can currently resolve:
|
|
1092
|
-
|
|
1093
|
-
```bash
|
|
1094
|
-
hexgate chat --list-agents
|
|
1095
|
-
```
|
|
1096
|
-
|
|
1097
1132
|
### `hexgate register` — push a manifest to the platform
|
|
1098
1133
|
|
|
1099
1134
|
Register a code-defined agent's manifest with the HexaGate platform. `--agent`
|
|
@@ -1,17 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# HexaGate
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
- `Linkup` web search
|
|
8
|
-
- Tavily-based page fetch
|
|
9
|
-
- `Langfuse` tracing
|
|
5
|
+
**Authorization infrastructure for AI agents.**
|
|
6
|
+
Policy enforcement, signed policy bundles, per-request user scope, audit trail — for OpenAI Agents, LangChain, Google ADK, Pydantic AI, or a native runtime.
|
|
10
7
|
|
|
11
|
-
|
|
8
|
+
[](https://pypi.org/project/hexgate/)
|
|
9
|
+
[](https://pypi.org/project/hexgate/)
|
|
10
|
+
[](https://github.com/HexamindOrganisation/hexgate/actions/workflows/tests.yml)
|
|
11
|
+
[](https://pypi.org/project/hexgate/)
|
|
12
|
+
[](LICENSE)
|
|
12
13
|
|
|
13
|
-
-
|
|
14
|
-
|
|
14
|
+
[Quick Start](#-quick-start--local-cli) · [Two paths](#-which-path-do-i-pick) · [Framework adapters](#-framework-agent-wrapping) · [Policy bundles](#-policy-bundles--compile-sign-enforce-wasm) · [User scope](#-user-scope--roles) · [Platform](#-hexagate-platform)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## What is HexaGate?
|
|
21
|
+
|
|
22
|
+
HexaGate is two things that move together:
|
|
23
|
+
|
|
24
|
+
- **`hexgate` — the SDK.** A Python runtime that gates every tool call through a typed `Decision` (allow / deny / approval-required), wraps your existing OpenAI / LangChain / Google ADK / Pydantic AI agent without rewriting it, and threads per-request user identity through tracing + audit.
|
|
25
|
+
- **The HexaGate platform** *(optional)* — a FastAPI control plane + React dashboard for editing policy in a browser, minting per-project tokens, watching live decisions stream from a serving agent, and shipping signed WASM policy bundles to production.
|
|
26
|
+
|
|
27
|
+
You can use the SDK with nothing else (single-process REPL, YAML on disk). Or plug in the platform when you want auditable decisions in ClickHouse, a shared Playground UI, and live policy edits.
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
┌─────────────────────────────────────────┐
|
|
31
|
+
your code ───► │ create_agent / wrap_*_agent / Runner │
|
|
32
|
+
│ ↓ │
|
|
33
|
+
│ PolicyEnforcer.decide(role, tool) │
|
|
34
|
+
│ ↓ │
|
|
35
|
+
│ allow · deny · approval_required │
|
|
36
|
+
└────────────────────┬────────────────────┘
|
|
37
|
+
│
|
|
38
|
+
┌────────────────────────┼─────────────────────────┐
|
|
39
|
+
▼ ▼ ▼
|
|
40
|
+
┌────────────────┐ ┌──────────────────┐ ┌────────────────┐
|
|
41
|
+
│ Local policy │ │ Signed WASM │ │ Audit log │
|
|
42
|
+
│ (YAML / dir, │ │ bundle from │ │ (ClickHouse │
|
|
43
|
+
│ hot reload) │ │ HexaGate cloud │ │ via REST) │
|
|
44
|
+
└────────────────┘ └──────────────────┘ └────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Table of contents
|
|
48
|
+
|
|
49
|
+
- [Prerequisites](#-prerequisites)
|
|
50
|
+
- [Quick Start — Local CLI](#-quick-start--local-cli)
|
|
51
|
+
- [Which path do I pick?](#-which-path-do-i-pick) — chat vs serve
|
|
52
|
+
- [Quick Start — Platform](#-quick-start--platform)
|
|
53
|
+
- [Core primitives](#-core-primitives)
|
|
54
|
+
- [Build an agent — end to end](#-build-an-agent--end-to-end)
|
|
55
|
+
- [What you can import](#-what-you-can-import)
|
|
56
|
+
- [Framework agent wrapping](#-framework-agent-wrapping) — OpenAI, LangChain, Google ADK, Pydantic AI
|
|
57
|
+
- [Define agents in code](#-define-agents-in-code)
|
|
58
|
+
- [Builtin and local agents](#-builtin-and-local-agents)
|
|
59
|
+
- [Policy shape](#-policy-shape)
|
|
60
|
+
- [Tool-call policy enforcement](#-tool-call-policy-enforcement)
|
|
61
|
+
- [Policy bundles — compile, sign, enforce (WASM)](#-policy-bundles--compile-sign-enforce-wasm)
|
|
62
|
+
- [Approval-required tool calls](#-approval-required-tool-calls)
|
|
63
|
+
- [Workspace sandbox](#-workspace-sandbox)
|
|
64
|
+
- [Environment](#-environment)
|
|
65
|
+
- [Tests & dev tooling](#-tests--dev-tooling)
|
|
66
|
+
- [CLI reference](#-cli-reference)
|
|
67
|
+
- [HexaGate platform](#-hexagate-platform)
|
|
68
|
+
- [User scope + roles](#-user-scope--roles)
|
|
69
|
+
- [Stream results](#-stream-results)
|
|
15
70
|
|
|
16
71
|
## 🛠️ Prerequisites
|
|
17
72
|
|
|
@@ -1023,41 +1078,18 @@ The platform-side test suite is separate and lives at `platform/api/tests/`:
|
|
|
1023
1078
|
cd platform/api && uv run pytest tests/
|
|
1024
1079
|
```
|
|
1025
1080
|
|
|
1026
|
-
##
|
|
1027
|
-
|
|
1028
|
-
Install the package into your current environment:
|
|
1029
|
-
|
|
1030
|
-
```bash
|
|
1031
|
-
python -m pip install -e .
|
|
1032
|
-
```
|
|
1081
|
+
## 🖥️ CLI reference
|
|
1033
1082
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
```bash
|
|
1037
|
-
python examples/demo.py
|
|
1038
|
-
```
|
|
1039
|
-
|
|
1040
|
-
Run the inline chat CLI with a local or builtin YAML agent:
|
|
1041
|
-
|
|
1042
|
-
```bash
|
|
1043
|
-
hexgate chat --agent example_agent
|
|
1044
|
-
```
|
|
1045
|
-
|
|
1046
|
-
Run the CLI with code-defined agents from a Python script:
|
|
1083
|
+
The `hexgate` binary exposes `chat`, `serve`, `register`, and `policy` subcommands. The [Quick Start](#-quick-start--local-cli) covers `chat`; this section drills into `register` and `serve` for the platform path.
|
|
1047
1084
|
|
|
1048
1085
|
```bash
|
|
1086
|
+
hexgate --help # list subcommands
|
|
1087
|
+
hexgate <subcommand> --help # flags for a subcommand
|
|
1088
|
+
hexgate chat --list-agents # show resolvable agents
|
|
1049
1089
|
hexgate chat --use examples/file_agents.py --agent workspace_explorer
|
|
1050
|
-
hexgate chat --use examples/file_agents.py --agent repo_editor
|
|
1051
|
-
hexgate chat --use examples/research_agents.py --agent update_researcher
|
|
1052
1090
|
hexgate chat --use examples/research_agents.py --agent update_researcher --approval-mode ask
|
|
1053
1091
|
```
|
|
1054
1092
|
|
|
1055
|
-
List what the CLI can currently resolve:
|
|
1056
|
-
|
|
1057
|
-
```bash
|
|
1058
|
-
hexgate chat --list-agents
|
|
1059
|
-
```
|
|
1060
|
-
|
|
1061
1093
|
### `hexgate register` — push a manifest to the platform
|
|
1062
1094
|
|
|
1063
1095
|
Register a code-defined agent's manifest with the HexaGate platform. `--agent`
|
|
@@ -79,16 +79,32 @@ class HexgateRunner:
|
|
|
79
79
|
user: User,
|
|
80
80
|
**kwargs: Any,
|
|
81
81
|
) -> Generator[Any, None, None]:
|
|
82
|
-
"""Run the Google ADK agent synchronously, yielding events.
|
|
82
|
+
"""Run the Google ADK agent synchronously, yielding events.
|
|
83
|
+
|
|
84
|
+
ADK's ``Runner.run`` drives the agent loop in a worker thread whose
|
|
85
|
+
context cannot see our :class:`User` scope, so the tools' enforcers
|
|
86
|
+
lose the active role. We drive ``run_async`` inline on a per-call loop
|
|
87
|
+
instead, keeping execution in this scoped thread.
|
|
88
|
+
"""
|
|
83
89
|
self._setup_observability()
|
|
84
90
|
self._binding.refresh() # per-run policy pull; 304 when unchanged
|
|
85
91
|
with user.sync_scope(), self._propagate(user):
|
|
86
|
-
|
|
92
|
+
agen = self._runner.run_async(
|
|
87
93
|
user_id=user.user_id,
|
|
88
94
|
session_id=user.session_id,
|
|
89
95
|
new_message=new_message,
|
|
90
96
|
**kwargs,
|
|
91
97
|
)
|
|
98
|
+
loop = asyncio.new_event_loop()
|
|
99
|
+
try:
|
|
100
|
+
while True:
|
|
101
|
+
try:
|
|
102
|
+
yield loop.run_until_complete(agen.__anext__())
|
|
103
|
+
except StopAsyncIteration:
|
|
104
|
+
break
|
|
105
|
+
finally:
|
|
106
|
+
loop.run_until_complete(agen.aclose())
|
|
107
|
+
loop.close()
|
|
92
108
|
|
|
93
109
|
async def run_async(
|
|
94
110
|
self,
|
|
@@ -134,21 +134,22 @@ class HexgateRunner:
|
|
|
134
134
|
) -> RunResultStreaming:
|
|
135
135
|
"""Stream the OpenAI agent inside a User scope.
|
|
136
136
|
|
|
137
|
-
``Runner.run_streamed`` returns sync
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
the
|
|
137
|
+
``Runner.run_streamed`` returns sync but spawns the agent loop as a
|
|
138
|
+
background task that snapshots the current contextvars at creation;
|
|
139
|
+
tools fire there, not in ``stream_events``. So the User scope must be
|
|
140
|
+
active around the ``run_streamed`` call for the task to inherit it —
|
|
141
|
+
the wrapped iterator re-opens it for exit/audit semantics.
|
|
142
142
|
"""
|
|
143
143
|
self._setup_observability()
|
|
144
144
|
binding = self._binding_for(agent)
|
|
145
145
|
binding.refresh() # must precede the wrap + setup
|
|
146
146
|
wrapped_agent = wrap_openai_agent(agent, enforcer=binding.enforcer)
|
|
147
147
|
|
|
148
|
-
with
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
with user.sync_scope():
|
|
149
|
+
with self._propagate(user, agent.name):
|
|
150
|
+
result = Runner.run_streamed(
|
|
151
|
+
wrapped_agent, input, run_config=run_config, **kwargs
|
|
152
|
+
)
|
|
152
153
|
|
|
153
154
|
original_stream_events = result.stream_events
|
|
154
155
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexgate
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: HexaGate — authorization infrastructure for AI agents (agent runtime + cloud client).
|
|
5
|
+
License-Expression: MIT
|
|
5
6
|
Requires-Python: >=3.13
|
|
6
7
|
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
7
9
|
Requires-Dist: bashlex>=0.18
|
|
8
10
|
Requires-Dist: biscuit-python>=0.4
|
|
9
11
|
Requires-Dist: cryptography>=42
|
|
@@ -33,21 +35,77 @@ Requires-Dist: jupyter; extra == "dev"
|
|
|
33
35
|
Requires-Dist: pytest>=8.4.1; extra == "dev"
|
|
34
36
|
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
35
37
|
Requires-Dist: ruff>=0.12.2; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
<div align="center">
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
# HexaGate
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
- `Linkup` web search
|
|
44
|
-
- Tavily-based page fetch
|
|
45
|
-
- `Langfuse` tracing
|
|
44
|
+
**Authorization infrastructure for AI agents.**
|
|
45
|
+
Policy enforcement, signed policy bundles, per-request user scope, audit trail — for OpenAI Agents, LangChain, Google ADK, Pydantic AI, or a native runtime.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
[](https://pypi.org/project/hexgate/)
|
|
48
|
+
[](https://pypi.org/project/hexgate/)
|
|
49
|
+
[](https://github.com/HexamindOrganisation/hexgate/actions/workflows/tests.yml)
|
|
50
|
+
[](https://pypi.org/project/hexgate/)
|
|
51
|
+
[](LICENSE)
|
|
48
52
|
|
|
49
|
-
-
|
|
50
|
-
|
|
53
|
+
[Quick Start](#-quick-start--local-cli) · [Two paths](#-which-path-do-i-pick) · [Framework adapters](#-framework-agent-wrapping) · [Policy bundles](#-policy-bundles--compile-sign-enforce-wasm) · [User scope](#-user-scope--roles) · [Platform](#-hexagate-platform)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## What is HexaGate?
|
|
60
|
+
|
|
61
|
+
HexaGate is two things that move together:
|
|
62
|
+
|
|
63
|
+
- **`hexgate` — the SDK.** A Python runtime that gates every tool call through a typed `Decision` (allow / deny / approval-required), wraps your existing OpenAI / LangChain / Google ADK / Pydantic AI agent without rewriting it, and threads per-request user identity through tracing + audit.
|
|
64
|
+
- **The HexaGate platform** *(optional)* — a FastAPI control plane + React dashboard for editing policy in a browser, minting per-project tokens, watching live decisions stream from a serving agent, and shipping signed WASM policy bundles to production.
|
|
65
|
+
|
|
66
|
+
You can use the SDK with nothing else (single-process REPL, YAML on disk). Or plug in the platform when you want auditable decisions in ClickHouse, a shared Playground UI, and live policy edits.
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
┌─────────────────────────────────────────┐
|
|
70
|
+
your code ───► │ create_agent / wrap_*_agent / Runner │
|
|
71
|
+
│ ↓ │
|
|
72
|
+
│ PolicyEnforcer.decide(role, tool) │
|
|
73
|
+
│ ↓ │
|
|
74
|
+
│ allow · deny · approval_required │
|
|
75
|
+
└────────────────────┬────────────────────┘
|
|
76
|
+
│
|
|
77
|
+
┌────────────────────────┼─────────────────────────┐
|
|
78
|
+
▼ ▼ ▼
|
|
79
|
+
┌────────────────┐ ┌──────────────────┐ ┌────────────────┐
|
|
80
|
+
│ Local policy │ │ Signed WASM │ │ Audit log │
|
|
81
|
+
│ (YAML / dir, │ │ bundle from │ │ (ClickHouse │
|
|
82
|
+
│ hot reload) │ │ HexaGate cloud │ │ via REST) │
|
|
83
|
+
└────────────────┘ └──────────────────┘ └────────────────┘
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Table of contents
|
|
87
|
+
|
|
88
|
+
- [Prerequisites](#-prerequisites)
|
|
89
|
+
- [Quick Start — Local CLI](#-quick-start--local-cli)
|
|
90
|
+
- [Which path do I pick?](#-which-path-do-i-pick) — chat vs serve
|
|
91
|
+
- [Quick Start — Platform](#-quick-start--platform)
|
|
92
|
+
- [Core primitives](#-core-primitives)
|
|
93
|
+
- [Build an agent — end to end](#-build-an-agent--end-to-end)
|
|
94
|
+
- [What you can import](#-what-you-can-import)
|
|
95
|
+
- [Framework agent wrapping](#-framework-agent-wrapping) — OpenAI, LangChain, Google ADK, Pydantic AI
|
|
96
|
+
- [Define agents in code](#-define-agents-in-code)
|
|
97
|
+
- [Builtin and local agents](#-builtin-and-local-agents)
|
|
98
|
+
- [Policy shape](#-policy-shape)
|
|
99
|
+
- [Tool-call policy enforcement](#-tool-call-policy-enforcement)
|
|
100
|
+
- [Policy bundles — compile, sign, enforce (WASM)](#-policy-bundles--compile-sign-enforce-wasm)
|
|
101
|
+
- [Approval-required tool calls](#-approval-required-tool-calls)
|
|
102
|
+
- [Workspace sandbox](#-workspace-sandbox)
|
|
103
|
+
- [Environment](#-environment)
|
|
104
|
+
- [Tests & dev tooling](#-tests--dev-tooling)
|
|
105
|
+
- [CLI reference](#-cli-reference)
|
|
106
|
+
- [HexaGate platform](#-hexagate-platform)
|
|
107
|
+
- [User scope + roles](#-user-scope--roles)
|
|
108
|
+
- [Stream results](#-stream-results)
|
|
51
109
|
|
|
52
110
|
## 🛠️ Prerequisites
|
|
53
111
|
|
|
@@ -1059,41 +1117,18 @@ The platform-side test suite is separate and lives at `platform/api/tests/`:
|
|
|
1059
1117
|
cd platform/api && uv run pytest tests/
|
|
1060
1118
|
```
|
|
1061
1119
|
|
|
1062
|
-
##
|
|
1063
|
-
|
|
1064
|
-
Install the package into your current environment:
|
|
1065
|
-
|
|
1066
|
-
```bash
|
|
1067
|
-
python -m pip install -e .
|
|
1068
|
-
```
|
|
1120
|
+
## 🖥️ CLI reference
|
|
1069
1121
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
```bash
|
|
1073
|
-
python examples/demo.py
|
|
1074
|
-
```
|
|
1075
|
-
|
|
1076
|
-
Run the inline chat CLI with a local or builtin YAML agent:
|
|
1077
|
-
|
|
1078
|
-
```bash
|
|
1079
|
-
hexgate chat --agent example_agent
|
|
1080
|
-
```
|
|
1081
|
-
|
|
1082
|
-
Run the CLI with code-defined agents from a Python script:
|
|
1122
|
+
The `hexgate` binary exposes `chat`, `serve`, `register`, and `policy` subcommands. The [Quick Start](#-quick-start--local-cli) covers `chat`; this section drills into `register` and `serve` for the platform path.
|
|
1083
1123
|
|
|
1084
1124
|
```bash
|
|
1125
|
+
hexgate --help # list subcommands
|
|
1126
|
+
hexgate <subcommand> --help # flags for a subcommand
|
|
1127
|
+
hexgate chat --list-agents # show resolvable agents
|
|
1085
1128
|
hexgate chat --use examples/file_agents.py --agent workspace_explorer
|
|
1086
|
-
hexgate chat --use examples/file_agents.py --agent repo_editor
|
|
1087
|
-
hexgate chat --use examples/research_agents.py --agent update_researcher
|
|
1088
1129
|
hexgate chat --use examples/research_agents.py --agent update_researcher --approval-mode ask
|
|
1089
1130
|
```
|
|
1090
1131
|
|
|
1091
|
-
List what the CLI can currently resolve:
|
|
1092
|
-
|
|
1093
|
-
```bash
|
|
1094
|
-
hexgate chat --list-agents
|
|
1095
|
-
```
|
|
1096
|
-
|
|
1097
1132
|
### `hexgate register` — push a manifest to the platform
|
|
1098
1133
|
|
|
1099
1134
|
Register a code-defined agent's manifest with the HexaGate platform. `--agent`
|
|
@@ -9,9 +9,11 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
# 0.2.0 (the original package name was taken on PyPI by a 2014
|
|
10
10
|
# abandoned project; the team consolidated on `hexgate` for everything).
|
|
11
11
|
name = "hexgate"
|
|
12
|
-
version = "0.2.
|
|
12
|
+
version = "0.2.2"
|
|
13
13
|
description = "HexaGate — authorization infrastructure for AI agents (agent runtime + cloud client)."
|
|
14
14
|
readme = "README.md"
|
|
15
|
+
license = "MIT"
|
|
16
|
+
license-files = ["LICENSE"]
|
|
15
17
|
requires-python = ">=3.13"
|
|
16
18
|
dependencies = [
|
|
17
19
|
"bashlex>=0.18",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|