@ujexdev/client
v0.3.0
Published
TypeScript client for Ujex Inbox, approvals, evidence, Provenance, tools, budgets, and advanced compatibility namespaces.
Maintainers
Readme
@ujexdev/client
TypeScript client for the Ujex control plane. The stable first-run surface is Inbox + Approvals + Evidence + Provenance; secondary namespaces remain available for advanced deployments.
Install
npm install @ujexdev/client firebaseMint an agent
On https://app.ujex.dev/settings → Create agent. Save the returned
agentId and deviceKey — the key is shown once.
Use
import {UjexClient, inboxIsReady} from '@ujexdev/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 email, optionally gated by human approval
await ap.postbox.send({
to: ['[email protected]'],
subject: 'hi',
body: '...',
sessionId: 'sess_run_20260618_001',
requireHuman: true,
});
// ask a human for approval
const {id} = await ap.mobile.ask({prompt: 'Transfer $50?', ttlSec: 300});
const decision = await ap.mobile.get({approvalId: id});
// write and search durable Provenance
await ap.memory.write({
name: 'vendor-acme',
type: 'project',
content: 'Acme prefers invoices on Friday.',
sessionId: 'sess_run_20260618_001',
});
const {hits} = await ap.memory.search({
query: 'invoice preference',
k: 5,
sessionId: 'sess_run_20260618_001',
});
// list inboxes — an address may be RESERVED, not live
const {inboxes} = await ap.postbox.listInboxes({});
for (const inbox of inboxes) {
// Mailbox provisioning is deferred from agent creation, so check readiness
// before you rely on the address. `inboxIsReady` also covers a provisioned
// mailbox an operator has disabled, which `mailState` alone cannot see.
if (!inboxIsReady(inbox)) {
console.warn(`${inbox.address} is ${inbox.mailState}: ${inbox.mailStateReason}`);
}
}
// KMS-backed secrets
await ap.secrets.store({agentId: 'me', name: 'openai_key', value: 'sk-...'});
const {value} = await ap.secrets.get({name: 'openai_key', sessionId: 'sess_run_20260618_001'});Subsystems
| Namespace | What it does |
|-----------|--------------|
| postbox | Inbox API — inbound webhooks, outbound relay, approval-gated sends, prompt-injection risk signals. listInboxes returns mailState/mailStateReason/ready per inbox (0.3.0); use inboxIsReady rather than assuming an address is live |
| mobile | Ask a human, receive a decision, and audit the result |
| memory | Markdown-first Provenance surface: list/read/write/append/delete/search/index |
| audit | Agent-scoped audit feed; owner evidence export remains in the dashboard |
| recall | Legacy Provenance aliases kept for compatibility |
| gateway | Advanced compatibility surface; not part of the launch path |
| artifacts | Advanced compatibility surface; signed URLs, grants, TTL reaping |
| scheduler | Advanced compatibility surface; cron jobs with HMAC-signed webhooks |
| secrets | Cloud KMS envelope encryption |
Generate one stable sessionId per agent run and pass it to every outbound
send, tool invocation, secret read, and memory operation. Ujex uses it for
prompt-injection poisoning, exfiltration checks, approval binding, and budget
preflight.
Rotating keys
Device keys are hashed; the plaintext is only shown at mint time. Create, rotate, revoke, and export evidence with human owner auth in the dashboard. Compatibility methods for human-only operations reject locally when called on the agent-authenticated client.
