synoi-gap Python SDK
Python SDK for the GAP (Governed Action Protocol). Provides OID computation, shape validators, and a thin async HTTP client for GAP-conformant gateways.
Install
pip install synoi-gap # core: OID + validators, no dependencies
pip install synoi-gap[http] # adds httpx for GapClient
Requires Python 3.9 or later.
OID computation
from synoi_gap import compute_gap_oid
payload = {
"type": "gap:capability_declaration",
"tenant_id": "tenant-abc",
"created_at_ms": 1750000000000,
"created_by": "sha256:actor...",
"body": {
"actor_type": "service",
"actor_id": "my-service",
"actor_name": "My Service",
"actor_version": "1.0.0",
"capabilities": [{"capability": "skill.create"}],
},
}
oid = compute_gap_oid(payload)
# "sha256:<64 hex chars>"
The excluded fields (oid, gap_version, signature, signature_key_id,
supersedes) are stripped automatically before hashing. You can pass the full
envelope or the stripped payload: the result is the same.
Validators
from synoi_gap import validate_cdro_envelope, validate_capability_declaration
errors = validate_cdro_envelope(envelope)
if errors:
raise ValueError(errors)
errors = validate_capability_declaration(decl)
Validators return a list of error strings. An empty list means the shape is
valid. They are not exhaustive and do not certify GAP conformance: they
catch the fields most commonly omitted by new implementors. For full
conformance checking, run against a L1+ conformant gateway or the
TypeScript validators in @synoi/gap.
GapClient (async HTTP)
import asyncio
from synoi_gap.client import GapClient
async def main():
async with GapClient(
base_url="https://gateway.synoi.systems/v1/gap",
token="synoi-sk-...",
tenant_id="tenant-abc",
) as client:
# Phase 1: declare
decl = await client.post_declaration(declaration_envelope)
# Phase 2: grant
grant = await client.post_grant(grant_envelope)
# Phase 3: invoke
receipt = await client.invoke(invocation_envelope)
# Phase 4: read receipt
full_receipt = await client.get_receipt(receipt["oid"])
asyncio.run(main())
See synoi_gap/client.py for the full method list (revocation, workflow
signals, key fetch).
OpenJarvis integration
synoi_gap.integrations.openjarvis provides a drop-in governance hook for
OpenJarvis agents. Wire it into OrchestratorAgent via the before_tool_call
parameter (see examples/openjarvis_pr_patch.py
for the upstream PR that adds that hook).
import asyncio
from synoi_gap.client import GapClient
from synoi_gap.integrations.openjarvis import GapToolHook, denied_tool_result
async def main():
async with GapClient(
base_url="https://gateway.synoi.systems/v1/gap",
token="synoi-sk-...",
tenant_id="tenant-abc",
) as gap:
hook = GapToolHook(
client=gap,
tenant_id="tenant-abc",
actor_oid="sha256:<agent-oid>",
grant_oid="sha256:<grant-oid>",
)
# With the upstream hook wired:
agent = OrchestratorAgent(engine, tools=tools, before_tool_call=hook)
await agent.run("do the thing")
# Or call manually before each tool:
allowed = await hook("shell_exec", {"command": "ls -la"})
if not allowed:
result = denied_tool_result("shell_exec")
asyncio.run(main())
Capability map: 30 OpenJarvis tool names are mapped to GAP capability
names (e.g. shell_exec -> system.shell.exec). Unknown tools map to
openjarvis.<tool_name> and are evaluated by gateway policy.
Safety classes: 9 tools are Class C (HITL required before execution):
shell_exec, docker_shell_exec, file_write, apply_patch, git_tool,
http_request, db_query, channel_tools, skill_manage. All others are
Class B (receipt issued, no human gate).
HITL polling: when the gateway defers a Class C decision, the hook polls
/receipts/{oid} until a human approves or denies via SMS, Slack, or
dashboard. Default timeout is 300 seconds; configurable via hitl_timeout.
See examples/openjarvis_example.py for a runnable dry-run demo (no credentials needed).
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synoi_gap-0.1.0.tar.gz.
File metadata
- Download URL: synoi_gap-0.1.0.tar.gz
- Upload date:
- Size: 22.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6603b491f44f4671befc59ea5523ab620e06d726b07d2b2a8dc9d4891de8753d
|
|
| MD5 |
8e1eb3ad8732824aea6f7f09819c1e82
|
|
| BLAKE2b-256 |
9ed7772ae7bd267eb046cc105277cba8e3e4e04dee25d313db6dfcb54ba22271
|
File details
Details for the file synoi_gap-0.1.0-py3-none-any.whl.
File metadata
- Download URL: synoi_gap-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
143f418bff1525888766e0611af6ffcc73dfc4984c01009875117aedc4558cae
|
|
| MD5 |
10433b29207dfd260f1f6eb6611d9a5a
|
|
| BLAKE2b-256 |
34482703a7082bfe80f2b79ad4e5ad1eeba6bdb3d68389af79162e411fb32689
|