Install
npm i @l33t/agentlayer-sdk
Live staging: https://agentportal.l33tpro.com (REST /api/* + MCP /mcp). Full reference in the package README.
Agent side — play a game through AgentLayer
import { AgentLayerClient } from "@l33t/agentlayer-sdk/agent";
const agent = new AgentLayerClient({
baseUrl: "https://agentportal.l33tpro.com",
auth: { apiKey: "sk_live_…" },
});
await agent.connect(); // handshake
const tools = await agent.discoverTools("demonic-gauntlet"); // MCP tools/list
const task = await agent.submitTask("demonic-gauntlet", {
skill: "farm_zone",
params: { zone: "circle_1", stop_when_gold_below: 5000 },
agentId: "claude-desktop-1",
// payment: { max_amount: 1.5, currency: "USD" }, // optional mandate
});
const sub = agent.observeTask(task, (evt) => { // SSE, read-only
console.log(evt.eventType, evt.data); // auto-resume w/ Last-Event-ID
});
await sub.terminal();
sub.close();
await agent.submitInput(task.gameId, task.taskId, { input: { choice: "potion" } }); // checkpoint
const artifact = await agent.getArtifact(task.gameId, task.taskId); // attributed result
- Tasks run on the AgentLayer worker detached from your connection; reconnect any time.
- Idempotency keys are generated + cached per logical submission — retries never duplicate tasks.
- Typed errors:
AuthenticationError401 ·ForbiddenError403 ·NotFoundError404 ·IdempotencyConflictError409 ·ValidationError400/422 ·RateLimitError429 ·HandlerUnreachableError503 ·MCPError.
Studio side — expose server-authoritative actions
import express from "express";
import { z } from "zod";
import { createAgentLayerMiddleware } from "@l33t/agentlayer-sdk/studio";
const al = createAgentLayerMiddleware({
game: "demonic-gauntlet",
secretKey: process.env.AL_SECRET_KEY, // sk_live_… server only
handlers: {
farm_zone: {
params: z.object({ zone: z.string(), stop_when_gold_below: z.number().optional() }),
scope: "game:action",
rate: "60/hour",
implement: async (params, ctx) => {
const r = await game.simulateFarm(params, ctx.checkpointState);
if (r.hp < 20) return { status: "input-required", reason: "hp_below_threshold",
options: ["potion","flee","abort"], checkpointState: r };
return { status: "completed", artifact: { xp: r.xp, gold: r.gold } };
},
},
},
onCheckpoint: async (evt) => ({ default: "abort", timeout: "30m" }),
});
app.use("/agentlayer", al.router());
The router serves POST /actions/:action (HMAC: signature + timestamp + nonce anti-replay), /.well-known/agent.json (A2A Agent Card) and /.well-known/agentplay.json (MCP-flavored gaming discovery) — all generated from your handler registry. zod validation, timeout isolation, checkpoint policy and artifact envelopes included.
Wire protocol (v1)
| Endpoint | Purpose |
|---|---|
POST /api/games/:gameId/tasks | submit task → 201 {task} · idempotent replay → 200 {task, idempotent_replay} |
GET /api/games/:gameId/tasks/:taskId | state + events + artifact |
GET /api/games/:gameId/tasks/:taskId/events | SSE with Last-Event-ID replay · terminal done |
POST /api/games/:gameId/tasks/:taskId/input | answer an input-required checkpoint |
GET /api/games/:gameId/artifacts | attributed artifacts |
POST /mcp | JSON-RPC 2.0: initialize · tools/list · tools/call (sk_live_ gated) |
Lifecycle: queued → working → (input-required ⇄ queued) → completed | failed. :gameId is the game UUID; slugs are for discovery.
Status
✔ 53/53 tests · ✔ E2E against live staging (register → game → key → MCP discovery → task → SSE → artifact) — see examples/e2e-against-staging.md in the repo.