@withgateway/agent-client
v0.1.0
Published
TypeScript SDK for the Gateway Agent Runtime (OpenHands-backed).
Downloads
16
Readme
@withgateway/agent-client
TypeScript SDK for the Gateway Agent Runtime (OpenHands-backed). Drive provisioned agents from your own code, addressable by agent ID.
Install
npm install @withgateway/agent-clientQuickstart
import { Gateway } from "@withgateway/agent-client";
const gw = new Gateway({
apiKey: { publicKey: "pk-lf-...", secretKey: "sk-lf-..." },
baseUrl: "https://withgateway.ai",
});
// Lazy handle — no fetch until you call something.
const agent = gw.agents.get(agentId);
const { runId, stream } = await agent.messages.send({
content: "Audit the last failing eval and open a PR with a fix.",
});
for await (const evt of stream) {
console.log(evt.kind, "runId:", evt.runId);
}
// Or get the run later by ID:
const run = await agent.runs.get(runId);
// Replay events for a finished run.
for await (const evt of agent.runs.stream(runId)) {
console.log(evt);
}Capability swap
Every owned subsystem (sandbox, cron, callback, file store, secrets, tracing, memory) can be swapped per-agent without redeploying anything.
await agent.capabilities.upsert("sandbox", {
provider: "external",
mode: "external",
config: { url: "https://sandbox.acme.internal" },
secretRefs: ["ACME_SANDBOX_TOKEN"],
});
await agent.capabilities.upsert("tracing", {
provider: "external",
mode: "hybrid", // also keeps Gateway observability
config: { url: "https://otel.acme.internal/v1/traces" },
});Cron jobs
await agent.cronJobs.create({
name: "Nightly review",
cronExpression: "0 */6 * * *",
prompt: "Run the nightly review checklist.",
});Coding-agent PRs
If your agent is the org's default coding agent (preset = "coding"), list the PRs it has opened:
const prs = await agent.prs.list({ limit: 20 });
for (const pr of prs) {
console.log(pr.prRepo, pr.prNumber, pr.prUrl, pr.prStatus);
}Integrations
List org-level integration installations (GitHub App, Slack workspace):
const integrations = await gw.integrations.org.list(orgId);
for (const i of integrations) console.log(i.provider, i.status);
// Disconnect:
await gw.integrations.org.unlink(orgId, "slack");Install/auth flows still go through the cookie-authed OAuth redirects because they require a browser. Direct your users to:
https://{baseUrl}/api/integrations/github/install?orgId=...https://{baseUrl}/api/integrations/slack/install?orgId=...https://{baseUrl}/api/integrations/github/auth?orgId=...(per-user)
Lifecycle
const instance = await agent.fetch();
if (instance.status === "PAUSED") await agent.resume();
await agent.pause();
await agent.terminate();Error handling
import { AuthError, CapabilityDisabledError } from "@withgateway/agent-client";
try {
await agent.messages.send({ content: "..." });
} catch (err) {
if (err instanceof CapabilityDisabledError) {
// sandbox / tools / tracing intentionally off for this agent
}
if (err instanceof AuthError) {
// bad key
}
}Implementation notes
- ESM + CJS dual build via
tsup - Auth header:
Authorization: Basic base64(publicKey:secretKey) - Streaming uses
fetch+ReadableStreamparsing of SSE — works on Node 18+, all modern browsers, edge runtimes (noEventSourcebecause we need custom headers) - Errors surface as typed
GatewayErrorsubclasses
