Build
SDKs — Python & TypeScript
Zero-config wrappers with first-class types, client-side redaction, deterministic idempotency, and server long-poll. Same wire contract, feature parity.
Error taxonomy
Always handle the three terminal outcomes — they are distinct on purpose.
from pliuz import (
PliuzRejectedError, # human said no (e.reason)
PliuzApprovalExpiredError, # server SLA hit before a decision
PliuzApprovalTimeoutError, # your polling gave up; may resolve later
PliuzEditNotApplicableError, # human edited args you can't auto-apply
)TypeScript mirrors these as typed subclasses (PliuzRejectedError, etc.) with correct instanceof across ESM/CJS.
Idempotency — read before relying on it
The key is hashed over pre-redaction args, so two calls differing only in a redacted field get different keys. The backend dedupes within a 24h window, per agent, and rejects the same key with a different payload (409). For legitimately repeating calls, set a per-run session_id.
# Repeating identical calls (crons, queues)? Scope per run so each
# run gets its own approval (the dedupe window is per (tool,args,session)).
@gated(policy="refund", session_id=run_id)
def refund(order_id: str): ...Decision latency (long-poll)
The wait is delivered by server long-poll: each call holds the connection up to ~25s and returns the instant the decision lands. Near-zero delivery latency and ~12x fewer requests than fixed-interval polling — no configuration needed.
Human edits
If an approver chooses Edit & Approve, the SDK executes the edited args, never the original call. With a custom toolArgs mapper (TS), provide applyFinalArgs or the SDK throws rather than run unapproved args.
Framework adapters
- LangChain — Python (
gated_tool()) - Vercel AI SDK — TypeScript (
gatedTool()) - Claude Agent SDK — Python & TypeScript
- OpenAI Agents SDK — Python & TypeScript
from langchain_core.tools import tool
from pliuz.adapters.langchain import gated_tool
@gated_tool(policy="refund", redact=["customer.ssn"])
@tool
def issue_refund(customer_id: str, amount_cents: int) -> str:
"""Issue a refund to a customer."""
return stripe.refunds.create(...).idManagement API (ManagementClient)
Provision agents, policies, and tools from your own code with the ManagementClient — a machine-token client (reads PLIUZ_MANAGEMENT_KEY) that ships in both SDKs: sync in Python, async in TypeScript. It uses scoped least-privilege tokens and never runs approvals or mints agent keys. See Management API.