| title | Python SDK |
|---|---|
| description | Thin subprocess wrapper over the Gait CLI for Python integrations with zero external dependencies. |
The Python SDK (sdk/python/gait) is a thin subprocess wrapper over the local gait binary.
Important boundary:
- Go CLI/Core is authoritative for policy, signing, canonicalization, verification, and exit semantics.
- Python intentionally does not reimplement those behaviors; it shells out to
gaitand returns structured results.
Supported primitives:
- intent capture (
capture_intent) - gate evaluation (
evaluate_gate) - demo capture (
capture_demo_runpack, viagait demo --json) - regress fixture init (
create_regress_fixture) - run capture (
record_runpack) - trace copy/validation (
write_trace) - optional LangChain middleware (
GaitLangChainMiddleware)
Non-goals:
- no policy parsing/evaluation in Python
- no alternate artifact canonicalization/signing logic
- no hosted transport dependency
The SDK executes commands via subprocess.run(...) with a bounded timeout.
- default timeout:
30s - JSON-decoding is strict for command responses expected to be JSON
- demo capture consumes machine-readable
gait demo --jsonoutput only - non-zero exits raise
GaitCommandErrorwith command, exit code, stdout, and stderr run_session(...)delegates digest-bearing runpack fields togait run record; Go computes or validatesargs_digest,result_digest, and trace receipt digests before artifact emission- unsupported non-JSON values such as Python
setare rejected deterministically; convert them to stable JSON types before calling the SDK
If existing wrapper automation scraped the human gait demo text output, switch it to capture_demo_runpack(...) or gait demo --json. The human text form is not a stable SDK contract.
The SDK expects gait to be available on PATH by default.
Override binary:
gait_bin="gait"(default)gait_bin="/absolute/path/to/gait"gait_bin=[sys.executable, "wrapper.py"](test harnesses)
Missing binary behavior:
- raises
GaitCommandErrorwith actionable message:- install
gait - ensure
PATHcontainsgait - or pass
gait_binexplicitly
- install
from gait import IntentContext, capture_intent, evaluate_gate
intent = capture_intent(
tool_name="tool.write",
args={"path": "/tmp/out.txt"},
context=IntentContext(identity="alice", workspace="/repo", risk_class="high"),
)
decision = evaluate_gate(
policy_path="examples/policy/base_high_risk.yaml",
intent=intent,
)
if decision.verdict != "allow":
raise RuntimeError(f"blocked: {decision.verdict} {decision.reason_codes}")Recommended sequence:
- run fixture policy tests in CI (
gait policy test,gait policy simulate) - evaluate in observe mode (
--simulate) through integration wrappers - enforce non-
allowas non-executable at the tool boundary
Reference docs:
docs/policy_rollout.mddocs/integration_checklist.md
The SDK is a thin subprocess wrapper that calls the local gait binary. The Go binary must be installed and on PATH.
No. The Python SDK has zero external runtime dependencies. Dev dependencies (pytest, ruff, mypy) are for development only.
LangChain is opt-in:
- install with
uv sync --extra langchain --extra devwhen you want the middleware surface - base SDK users do not need LangChain installed
Python 3.11 or higher.
No. sdk/python keeps repo-local dev metadata (0.0.0.dev0) and is not the public release signal. Use gait version --json for install automation, support intake, and release verification.
Use the @gate_tool decorator from the SDK. It automatically evaluates gate policy before executing the tool and records the result.
run_session(...) records raw normalization payloads and lets gait run record compute authoritative digests in Go/JCS. The SDK no longer synthesizes portable artifact digests locally.
The official surface is GaitLangChainMiddleware, and enforcement only happens in wrap_tool_call.
- tool name and args are captured into a normal
IntentRequest - execution still routes through
ToolAdapter.execute - optional
GaitLangChainCallbackHandlerreceives additive correlation metadata such asrun_id,request_id,trace_path,policy_digest, andintent_digest - callback handlers never decide allow or block behavior
- the official example lane is
examples/integrations/langchain/quickstart.py
Minimal snippet:
from gait import ToolAdapter
from gait.langchain import GaitLangChainMiddleware, GaitLangChainCallbackHandler
adapter = ToolAdapter(policy_path="examples/integrations/langchain/policy_allow.yaml")
middleware = [
GaitLangChainMiddleware(
adapter=adapter,
callback_handler=GaitLangChainCallbackHandler(),
)
]The SDK raises a clear error with install instructions and PATH guidance instead of an opaque FileNotFoundError.