Skip to main content

IntentGate Python SDK

CI PyPI version Python versions License: Apache 2.0

The official Python client for the IntentGate authorization gateway.

Companion repositories

Repo Purpose
intentgate-gateway Go gateway with the four-check pipeline. The thing this SDK talks to.
intentgate-extractor Optional FastAPI service that turns user prompts into structured intent.
intentgate-sdk-python Python SDK for agents (this repo).
intentgate-helm Helm chart that deploys the gateway, extractor, and Redis to Kubernetes.

What it is

A thin client that lets your AI agent call tools through the IntentGate gateway with a Pythonic API. The SDK handles the JSON-RPC envelope, the Bearer token, the X-Intent-Prompt header, and turns gateway error responses into typed Python exceptions.

Three lines of agent code

from intentgate import Gateway

gw = Gateway(url="http://localhost:8080", token=os.environ["INTENTGATE_TOKEN"])
result = gw.tool_call(
    "read_invoice",
    arguments={"id": "123"},
    intent_prompt="Process today's AP invoices",
)

That's it. Construct once, call as many times as you like. When the gateway blocks the call, tool_call raises a typed exception you can catch.

Install

pip install intentgate

Released versions are published to PyPI on every vX.Y.Z git tag via signed OIDC trusted publishing — see .github/workflows/release.yml.

To install the development tip:

pip install git+https://github.com/NetGnarus/intentgate-sdk-python.git

Exception hierarchy

Every blocked call raises an exception. The class tells you which gateway check fired:

Exception JSON-RPC code When
CapabilityError -32010 Token signature invalid, expired, agent mismatch, tool not in caveat allow-list.
IntentError -32011 Tool isn't in the intent extracted from the user prompt.
PolicyError -32012 OPA policy returned deny. The reason carries the Rego rule's explanation.
BudgetError -32013 A max_calls caveat in the token has been exhausted.
ProtocolError other JSON-RPC Malformed request, method not found, etc. Usually means an SDK ↔ gateway version mismatch.
GatewayError n/a Couldn't reach the gateway, or got a non-2xx HTTP response.
IntentGateError (base) Catch this if you don't care which check fired.
from intentgate import Gateway, PolicyError, BudgetError, IntentGateError

try:
    result = gw.tool_call("transfer_funds", arguments={"amount_eur": 50_000})
except PolicyError as e:
    log.warning("policy blocked: %s (%s)", e.message, e.data)
except BudgetError:
    log.error("agent ran out of budgeted calls")
except IntentGateError as e:
    # everything else: re-raise or surface to user
    raise

API reference

Gateway(url, token=None, *, timeout=10.0, client=None)

Construct a client.

  • url — base URL of the gateway, e.g. http://localhost:8080. Trailing slash is tolerated.
  • token — capability token from igctl mint. When None, no Authorization header is sent.
  • timeout — per-request timeout in seconds.
  • client — pre-configured httpx.Client for advanced use (test injection, custom transports). The SDK only closes the client it created itself.

Gateway is also a context manager:

with Gateway(url="...", token="...") as gw:
    gw.tool_call(...)
# client closed automatically

Gateway.tool_call(tool, arguments=None, *, intent_prompt=None, request_id=None) -> ToolCallResult

Invoke a tool through the gateway.

  • tool — tool name like "read_invoice". Required.
  • arguments — pass-through dict to the tool. The gateway logs only the keys, never the values.
  • intent_prompt — the user's natural-language request. Sent as the X-Intent-Prompt header. Strongly recommended in production; without it the intent check is skipped (or denies in strict mode).
  • request_id — JSON-RPC id. Defaults to a per-Gateway sequential integer.

Returns a ToolCallResult with:

  • content: list[ContentBlock] — what the upstream tool returned (MCP shape, currently type="text" only).
  • is_error: bool — MCP-level "tool reported an error" flag (distinct from gateway-level errors that raise exceptions).
  • intentgate: IntentGateMetadata | None — gateway decision summary (decision, reason, check, latency_ms).

Typical usage in an agent

The pitch's "three lines" referred to the SDK setup. In practice an agent wraps each tool through the gateway:

from intentgate import Gateway

class FinanceAgent:
    def __init__(self, gateway_url: str, token: str, prompt: str) -> None:
        self.gw = Gateway(url=gateway_url, token=token)
        self.prompt = prompt

    def read_invoice(self, invoice_id: str) -> str:
        result = self.gw.tool_call(
            "read_invoice",
            arguments={"id": invoice_id},
            intent_prompt=self.prompt,
        )
        return result.content[0].text

    def transfer_funds(self, amount_eur: int, recipient: str) -> None:
        self.gw.tool_call(
            "transfer_funds",
            arguments={"amount_eur": amount_eur, "recipient": recipient},
            intent_prompt=self.prompt,
        )

Develop locally

make install     # creates .venv, installs -e ".[dev]"
make lint        # ruff check + ruff format --check
make lint-fix    # auto-fix lint + format
make test        # pytest
make build       # sdist + wheel into dist/ (sanity check before tagging a release)

Tests use respx to mock httpx at the transport level — no real network required, no running gateway needed.

Project layout

src/intentgate/
  __init__.py         # public API: Gateway, exceptions, dataclasses
  client.py           # Gateway client + ToolCallResult dataclasses
  exceptions.py       # IntentGateError hierarchy (CapabilityError, IntentError, ...)
tests/
  test_client.py      # respx-mocked HTTP behavior
.github/workflows/    # CI (lint + tests across Python 3.10–3.13) and release (publish to PyPI on tag)
Makefile              # install / lint / lint-fix / test / build / clean
pyproject.toml        # hatchling build, ruff config, pytest config

Versioning

Pre-release. The wire protocol with the gateway is stable (JSON-RPC 2.0 + the IntentGate-specific error codes), but the Python API surface may change before 1.0.0. Pin to a minor version when integrating.

Contributing

Apache 2.0 and welcomes community contributions. A formal CONTRIBUTING.md is coming with the v0.1 → v1.0 polish pass. For now, please open an issue to discuss any non-trivial change before sending a PR.

Security

If you find a security vulnerability, please do not open a public issue. Email security@netgnarus.com (or open a GitHub Security Advisory on this repo) and we'll respond within two business days.

Metadata

Release files for intentgate 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for intentgate 0.3.0
File Size Uploaded
intentgate-0.3.0.tar.gz 20.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for intentgate 0.3.0
File Interpreter ABI Platform
intentgate-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 38.7 kB

Release files / intentgate-0.3.0.tar.gz

Download URL intentgate-0.3.0.tar.gz
Size 20.3 kB
Tags Source
SHA-256 checksum
How to use checksums
352825ef241e8cbeb95f8903f228a90a432307d2d6d1596e5ebbc21428b4490f
BLAKE2b-256 checksum
How to use checksums
dbb1e32183bfc4b766ed971a4d016c8a55c9185e785028b1ef038a0dff65fa4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 10, 2026.

Transparency log

Release files / intentgate-0.3.0-py3-none-any.whl

Download URL intentgate-0.3.0-py3-none-any.whl
Size 18.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f1982d951fcff6f91e7699a4b31ac68fa229aa76e8885a472b9864886af15e4f
BLAKE2b-256 checksum
How to use checksums
1be1011c29c9da60cd65024d807632648ac74a7383af392da259ae85e93b57c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page