SDKs and CLIs
Ujex ships first-party clients in Python, TypeScript, Go, plus a standalone CLI and an MCP server so any MCP client (Claude Desktop, Cursor, Cline, Zed) can use the product directly.
The same OpenAPI 3.1 spec lives at /openapi.json — you can generate
clients in any language if the ones we ship aren't enough.
Python — ujex-postbox
pip install ujex-postbox
from ujex_postbox import PostboxClient, plus_address
client = PostboxClient(device_key="apk_...")
resp = client.send(
to=["alice@vendor.com"],
subject="Re: invoice",
body="On it — sending by Friday.",
)
print(resp.id, resp.status, resp.quota_remaining)
# Plus-address a per-task inbox for free (no new inbox needed)
addr = plus_address("agent-hello@ujex.dev", task_id="proj-42")
# Verify an inbound webhook
from ujex_postbox.webhook import verify_signature, parse_inbound_event
ok = verify_signature(raw_body=req.body, signature=req.headers["x-ujex-signature"], secret=SECRET)
Framework adapters (install one or more extras):
pip install 'ujex-postbox[langchain]'
pip install 'ujex-postbox[llamaindex]'
pip install 'ujex-postbox[crewai]'
from ujex_postbox.integrations.langchain import postbox_tools
tools = postbox_tools(client, agent_id="agent-hello")
# pass tools to any LangChain agent / graph
Async variant: AsyncPostboxClient.
TypeScript — @ujex/client
npm install @ujex/client firebase
import {UjexClient} from '@ujex/client';
const ap = new UjexClient({
firebase: {
apiKey: 'AIzaSy...',
authDomain: 'axy-ujex.firebaseapp.com',
projectId: 'axy-ujex',
appId: '1:...:web:...',
},
agentId: process.env.AP_AGENT_ID!,
deviceKey: process.env.AP_DEVICE_KEY!,
});
await ap.connect();
// Send with human approval
await ap.postbox.send({
to: ['alice@vendor.com'],
subject: 'hi',
body: '...',
requireHuman: true,
});
// Ask a human for approval
const {id} = await ap.mobile.ask({prompt: 'Send $800 invoice to Bob?', ttlSec: 300});
// Write and search durable memory
await ap.memory.write({name: 'alice-invoice', content: 'Alice prefers invoice email on Friday.'});
const hits = await ap.memory.search({query: 'alice invoice preference', k: 5});
Covers the core Ujex loop first: Postbox, Approvals, Audit, and Recall/Memory. Secondary namespaces such as Gateway, Scheduler, Tools, Identity, and Observe are available for advanced deployments.
Go — github.com/axysar/ujex/sdks/go/postbox
go get github.com/axysar/ujex/sdks/go/postbox
package main
import (
"context"
"fmt"
"os"
"github.com/axysar/ujex/sdks/go/postbox"
)
func main() {
client := postbox.NewClient(postbox.Options{
DeviceKey: os.Getenv("UJEX_DEVICE_KEY"),
})
resp, err := client.Send(context.Background(), postbox.SendParams{
To: []string{"alice@vendor.com"},
Subject: "Re: invoice",
Body: "On it.",
RequireHuman: true,
})
if err != nil {
if postbox.IsQuotaExceeded(err) {
// budget used up — wait until next month roll
}
panic(err)
}
fmt.Println(resp.ID, resp.Status)
}
Stdlib-only. Context-aware retries on 429/5xx with Retry-After respect.
CLI — ujex
# npm-global until the Homebrew tap lands
npm install -g @ujex/cli
ujex init <agentId> <deviceKey>
ujex send alice@vendor.com 'Re: invoice' 'On it.'
ujex ask 'Can I send the $800 invoice to Bob?'
ujex search 'promised alice invoice'
ujex mesh sync
ujex whoami
MCP server — @ujex/postbox-mcp
Give any MCP client (Claude Desktop, Cursor, Cline, Zed) direct control of an agent's inbox.
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ujex-postbox": {
"command": "npx",
"args": ["-y", "@ujex/postbox-mcp"],
"env": {
"UJEX_DEVICE_KEY": "apk_...",
"UJEX_AGENT_ID": "agent-hello"
}
}
}
}
Six tools become available to the LLM:
| Tool | Purpose |
|---|---|
postbox_send_email | Send an email. require_human=true blocks on mobile approval. |
postbox_list_messages | List recent inbound / outbound messages w/ pi_score. |
postbox_read_message | Read a single message + body + auth verdict. |
postbox_list_inboxes | Enumerate inboxes. |
postbox_create_plus_address | Build a per-task plus-address (local, no network). |
postbox_verify_inbound | Timing-safe HMAC check (local). |
Plus one resource: postbox://inbox/{agent_id} streams live mailbox snapshots into the LLM's context.
OpenAPI 3.1 spec
Machine-readable spec at /openapi.json. Covers the Postbox
surface with full request/response schemas, security schemes, example payloads, and
error response shapes (401 / 402 / 404 / 429). Use any code generator
(openapi-generator-cli, speakeasy, kiota) to produce a client in your language
of choice.
Which should I pick?
| You want… | Use |
|---|---|
| "Just wire this into LangChain / LlamaIndex / CrewAI" | Python SDK + the matching integration extra |
| Full Ujex surface, not just Postbox, in a web or Node backend | @ujex/client |
| A small, boring Go service that sends mail on behalf of an agent | Go SDK |
| Let me talk to Postbox from Claude Desktop / Cursor | MCP server |
| Scripting / ops one-liner | CLI |
| Any other language | OpenAPI spec + a generator |
All SDKs are Apache-2.0 and ship their source on GitHub.