SDKs

Official client libraries for Python, TypeScript, Java, and LangChain/LangGraph. Submit intents, retrieve decisions, handle errors — with full type safety.

At a Glance

Language Package Install Requirements
Python gaas-sdk pip install gaas-sdk Python 3.11+
TypeScript @gaas/sdk npm install @gaas/sdk Node.js 18+
Java com.gaas:gaas-sdk Maven / Gradle Java 17+
LangChain / LangGraph gaas-langchain pip install gaas-langchain Python 3.11+
All SDKs are Apache-2.0 licensed. Source and full documentation at github.com/H2OmAI/gaas under sdks/.

Python

Install

pip install gaas-sdk

Submit an Intent

from gaas_sdk import GaaSClient, build_intent, ActionType, TargetType

async with GaaSClient(
    "https://api.gaas.is",
    headers={"X-API-Key": "your_key"},
) as client:
    intent = build_intent(
        agent_id="billing_bot",
        action_type=ActionType.COMMUNICATE,
        verb="send_email",
        target_type=TargetType.PERSON,
        target_identifier="patient@example.com",
        summary="Send billing statement to patient",
        content={"recipient": "patient@example.com", "channel": "email"},
    )
    response = await client.submit_intent(intent)

    if response.data.verdict == "approve":
        send_email(response.data)
    elif response.data.verdict == "block":
        log(response.data.reasoning)

Sync Client

A synchronous client is available for non-async codebases:

from gaas_sdk import GaaSClientSync

with GaaSClientSync(
    "https://api.gaas.is",
    headers={"X-API-Key": "your_key"},
) as client:
    response = client.submit_intent(intent)

Bulk Submission

Submit up to 50 intents concurrently with partial failure support:

intents = [build_intent(...) for _ in range(10)]
response = await client.submit_intents_bulk(intents)

for result in response.data.results:
    if result.success:
        print(f"Decision: {result.decision.verdict}")
    else:
        print(f"Error: {result.error}")

Field Filtering

Request only specific fields to reduce response size:

response = await client.submit_intent(
    intent,
    fields="verdict,reasoning.summary,risk_assessment.overall_score"
)

Idempotency

Prevent duplicate submissions with idempotency keys (header-based recommended):

# Header-based (recommended)
response = await client.submit_intent(
    intent,
    headers={"Idempotency-Key": "unique-key-123"}
)

# Body-based (legacy)
intent = build_intent(
    idempotency_key="unique-key-123",
    agent_id="my-agent",
    # ...
)

Error Handling

from gaas_sdk import (
    GaaSError,
    GaaSValidationError,
    GaaSSemanticError,
    GaaSNotFoundError,
    GaaSConflictError,
    GaaSServerError,
    GaaSConnectionError,
)

try:
    response = await client.submit_intent(intent)
except GaaSValidationError as e:
    print(f"Validation failed (400): {e.message}")
except GaaSSemanticError as e:
    print(f"Semantic error (422): {e.message}")
except GaaSConflictError as e:
    print(f"Conflict (409): {e.message}")
except GaaSConnectionError:
    print("Could not reach GaaS server")
except GaaSError as e:
    # Catches all other GaaS errors (401, 402, 429, 500, etc.)
    print(f"GaaS error {e.code}: {e.message}")

Best Practices


TypeScript

Install

npm install @gaas/sdk

Submit an Intent

import { GaaSClient, buildIntent, ActionType, TargetType } from '@gaas/sdk';

const client = new GaaSClient({
  baseUrl: 'https://api.gaas.is',
  headers: { 'X-API-Key': 'your_key' },
});

const intent = buildIntent({
  agentId: 'billing_bot',
  actionType: ActionType.Communicate,
  verb: 'send_email',
  targetType: TargetType.Person,
  targetIdentifier: 'patient@example.com',
  summary: 'Send billing statement to patient',
  content: { recipient: 'patient@example.com', channel: 'email' },
});

const response = await client.submitIntent(intent);

if (response.data.verdict === 'approve') {
  sendEmail(response.data);
} else if (response.data.verdict === 'block') {
  console.log(response.data.verdictReason);
}
Automatic case conversion. The TypeScript SDK converts between camelCase (JavaScript) and snake_case (API) automatically. buildIntent({ agentId }) sends agent_id over the wire; response.data.riskAssessment comes from risk_assessment.

Error Handling

import { GaaSValidationError, GaaSConnectionError } from '@gaas/sdk';

try {
  const response = await client.submitIntent(intent);
} catch (error) {
  if (error instanceof GaaSValidationError) {
    console.error(`Validation failed: ${error.message}`);
  } else if (error instanceof GaaSConnectionError) {
    console.error('Could not reach GaaS server');
  }
}

Java

Install

Maven:

<dependency>
    <groupId>com.gaas</groupId>
    <artifactId>gaas-sdk</artifactId>
    <version>0.2.0</version>
</dependency>

Gradle:

implementation 'com.gaas:gaas-sdk:0.2.0'

Submit an Intent

import com.gaas.sdk.*;

try (GaaSClient client = new GaaSClient("https://api.gaas.is", "your_key")) {
    IntentDeclaration intent = IntentBuilder.create()
        .agentId("billing_bot")
        .actionType(ActionType.COMMUNICATE)
        .verb("send_email")
        .targetType(TargetType.PERSON)
        .targetIdentifier("patient@example.com")
        .summary("Send billing statement to patient")
        .content(Map.of("recipient", "patient@example.com", "channel", "email"))
        .build();

    GaaSResponse<GovernanceDecision> response = client.submitIntent(intent);

    if (response.getData().getVerdict() == Verdict.APPROVE) {
        sendEmail(response.getData());
    } else if (response.getData().getVerdict() == Verdict.BLOCK) {
        System.out.println(response.getData().getReasoning());
    }
}

Async API

CompletableFuture<GaaSResponse<GovernanceDecision>> future =
    client.submitIntentAsync(intent);

Error Handling

try {
    GaaSResponse<GovernanceDecision> response = client.submitIntent(intent);
} catch (GaaSValidationException e) {
    System.out.println("Validation failed: " + e.getMessage());
} catch (GaaSConnectionException e) {
    System.out.println("Could not reach GaaS server");
}

LangChain / LangGraph

Install

pip install gaas-langchain

Optional extras: pip install gaas-langchain[langchain], gaas-langchain[langgraph], or gaas-langchain[all].

Configuration

from gaas_langchain import GaaSGovernanceConfig

config = GaaSGovernanceConfig(
    api_url="https://api.gaas.is",
    api_key="gsk_your_key",
    agent_id="my-langchain-agent",
    block_on_escalate=True,     # raise on ESCALATE verdicts too
    timeout_seconds=5.0,
    sensitivity="INTERNAL",
)

Govern a Single Tool

from gaas_langchain import govern_tool

safe_tool = govern_tool(my_tool, config=config)
# safe_tool.run() and safe_tool.arun() now submit governance
# intents before execution. Blocked actions raise GovernanceBlockedError.

Govern Multiple Tools

from gaas_langchain import govern_tools

safe_tools = govern_tools([tool_a, tool_b, tool_c], config=config)

LangGraph Node Decorator

from gaas_langchain import govern_node

@govern_node(config=config, node_name="send_email_node", financial_exposure_usd=0.0)
async def send_email(state):
    # Only executes if governance approves
    return {"status": "sent"}

Supports both sync and async node functions. Uses functools.wraps to preserve function metadata. Additional parameters: sensitivity, regulatory_domains.

Callback Handler (Observability)

from gaas_langchain import GaaSCallbackHandler

handler = GaaSCallbackHandler(config, enforce=False)
# Pass as a LangChain callback — logs all governance decisions
# Set enforce=True to raise GovernanceBlockedError on BLOCK/ESCALATE

# After agent run:
print(handler.summary())
# {"total_tool_calls": 5, "approved": 4, "blocked": 1, "block_rate": 0.2, ...}
handler.reset()  # clear log between runs

Error Handling

from gaas_langchain import GovernanceBlockedError

try:
    result = safe_tool.run("send payment")
except GovernanceBlockedError as e:
    print(e.verdict)              # "BLOCK" or "ESCALATE"
    print(e.decision_id)           # GaaS decision ID
    print(e.risk_score)             # 0.0–1.0
    print(e.blocking_policies)      # ["pol_t1_002", ...]
    print(e.governance_proof_token)  # ECDSA-signed proof token ID

Common Patterns

Builder Pattern

All three SDKs provide a builder function (build_intent in Python, buildIntent in TypeScript, IntentBuilder in Java) that flattens the nested intent model into a flat argument list. This handles the agent.id, action.type, action.target.identifier nesting so you don't have to construct nested objects manually.

Response Structure

Every SDK method returns a typed response with two fields:

Retrieving Decisions

Python:

decision = await client.get_decision("intent-id")

TypeScript:

const decision = await client.getDecision('intent-id');

Java:

GaaSResponse<GovernanceDecision> decision = client.getDecision("intent-id");

Related Pages