Skip to content

Agent SDK

This SDK is behind the feature flag htpr-6115-agent-sdk, available by default only to your account.

The @hypertask/agent-sdk lets you build autonomous agents programmatically with a small TypeScript library that follows the same shape as Linear and Plane:

  • Agent = app with a bot identity
  • Run (AgentSession) = one session per interaction
  • Typed activity stream = thought, action, response, ask, error
  • Signals = stop, select, auth_request
  • Fast acknowledgement = post a thought within 10 seconds or the run becomes stale after 5 minutes

This SDK is the client-side counterpart to your agent infrastructure: it handles webhooks, signature verification, and typed activity recording so you can stand up a working agent in an afternoon.

Terminal window
npm install @hypertask/agent-sdk
# or
yarn add @hypertask/agent-sdk

The SDK includes adapters for common web frameworks and runtime environments. Use the webhook handler compatible with your stack.

AdapterSetupNotes
NodeAssign a TCP port to your Node server.Built-in; robust for single-process deployments.
Expressapp.use(webhookHandler) on an Express app.Classic middleware integrations.
Honoapp.use('*', webhookHandler) on a Hono app.Lightweight web framework.
Next.js API routeAttach to the default export route.Plugged into framework routing.
Cloudflare WorkersEnable automatic route at the Worker entry.Background support required; deduplication and buffering handled by the SDK.
Plain NodeRoute manually using raw request bytes and background support.Fully dependency-free but more manual wiring.

Create a simple agent that replies when mentioned and files its responses as activity rows in the ticket thread.

server.ts
import { createAgent } from '@hypertask/agent-sdk';
import express from 'express';
async function main() {
const app = express();
const { client, webhookHandler } = createAgent({
token: process.env.AGENT_TOKEN!,
secret: process.env.WEBHOOK_SECRET!,
});
// Attaches signature-verifying webhook handling to the Express app
app.use(webhookHandler);
// Your agent logic wired into events
client.on('mention', async (run) => {
await run.thought(`Being mentioned on ticket ${run.ticket.id}`);
await run.respond(`Noted: this is ticket ${run.ticket.id}.`);
});
client.on('assigned', async (run) => {
await run.thought(`Assigned to ticket ${run.ticket.id}`);
});
app.listen(3000, () => {
console.log('Agent running on port 3000');
});
}
main().catch(console.error);

For a complete example that works in under 30 minutes, check out the included reply-only template in the templates package:

templates/replyOnly.ts
import { createAgent } from '@hypertask/agent-sdk/templates/replyOnly';

Every event handler receives a run object that represents the current interaction. The run tracks the ticket, thread, status, and type-safe activity stream.

A run has one of these statuses during its lifetime:

StatusDescription
activeRunning and processing events
stoppedUser requested stop or error occurred
staleNo activity for 5 minutes after start
doneCompleted successfully

The run records all agent communication as typed activities in the thread, with muted styling like tool calls. Use these methods to write to the activity stream:

MethodWhen to Use
run.thought(text)Internal reasoning or planning
run.action(text, link)Tool execution or file attachment
run.respond(text)Agent response to the user
run.error(text)Handling failures or errors
run.ask(question, options)UX flows that require user input

All activity is persisted automatically when the SDK receives the mentioned or assigned event. You can also call activity methods on run directly.

Record an internal reasoning step.

client.on('mention', async (run) => {
await run.thought('Deciding which section to move the ticket to...');
});

Record an external action executed by the agent, with an optional file upload link.

await run.action('Test run started', 'https://hypertask.app/file/test-run-123.md');

Record the agent's user-facing response.

await run.respond("I'll move it to the Bug Severity 2 section.");

Record an error that you handled gracefully.

try {
// ...
} catch (err) {
await run.error('Failed to fetch from external API: ' + err.message);
}

Create a multi-choice prompt for user interaction. The return value is a promise that resolves to the user's choice.

const choice = await run.ask('Which section should this go to?', {
options: [
{ value: 'urgent', label: 'Urgent Priority' },
{ value: 'normal', label: 'Standard Priority' },
],
});
await run.respond(`Moving to ${choice.label}.`);

The run object gives you helper methods for the current ticket. These all include built-in lease management, so you don't need to call heartbeat manually.

HelperDescription
run.task.move(section)Move the task to a different section
run.task.assign(userId)Assign the task to a user
run.task.comment(text)Add a comment to the ticket
run.task.update(fields)Update task fields
run.task.attach(link)Attach a file or link

All helpers auto-heartbeat to keep your claim alive while work is in progress.

Move the current task to a different board section.

await run.task.move('Bug Severity 2');

Assign the task to a user by ID, email, or display name.

await run.task.assign(' me ');
await run.task.assign('john@example.com');

Add a comment to the task, which also appears in the thread.

await run.task.comment('Routing this through to the triage team.');

Update any task fields by writeable property name.

await run.task.update({
description: 'Updated based on the agent analysis...',
priority: 'High',
});

Attach a file or external link to the task.

await run.task.attach('https://hypertask.app/file/analysis-123.md');

Your agent can subscribe to one or more incoming events. All events provide a run object with ticket, thread, and helpers.

type EventHandler = (run: Run) => Promise<void>;
// Subscribe to all event types
client.on('*', handler);
// Subscribe to specific events
client.on('mention', mentionHandler);
client.on('assigned', assignedHandler);
client.on('chat', chatHandler);
client.on('stop', stopHandler);

Triggered when the agent is @mentioned in any comment or chat. Includes the full thread so far, the original prompt, and all existing activity.

client.on('mention', async (run) => {
// run.ticket: the ticket being mentioned
// run.thread: messages before this event
// run.prompt: the current task description or additional context
});

Triggered when the agent is assigned directly to a ticket via the interface.

client.on('assigned', async (run) => {
// run.ticket: the newly assigned ticket
});

Triggered when a message is sent in the Agent Chat. Useful for bots that respond in chat rather than on tickets.

client.on('chat', async (run) => {
// run.ticket: the task chat belongs to
// run.thread: all messages so far
});

Triggered when the agent's run is explicitly stopped by the user (e.g., via the agent control panel or chat interface). Use this for cleanup actions or confirmation posts.

client.on('stop', async (run) => {
await run.respond('Stopping work. Let me know if you need more.');
});

The SDK automatically emits signals that your agents can respond to. These are part of the run type and include request-and-response forms.

Users can request the agent to halt (via the agent control panel or chat). A stop signal clears the lease and stops further activity.

client.on('stop', async (run) => {
await run.respond('Stopped. No further actions.');
});

One-shot user choice prompts. Use run.ask(...) explicitly to get a promise-based choice, which renders as a multi-selector in the thread.

const choice = await run.ask(...);

Requests for additional authentication (e.g., missing OAuth tokens). Handled through your custom auth logic when the SDK can't automatically authenticate.

The SDK includes three ready-made templates you can use as starting points. All templates are available in the @hypertask/agent-sdk/templates package.

A minimal agent that only responds to mentions and chat, without touching tasks. Perfect for FAQs and bots that offer information but never modify state.

templates/replyOnly.ts
import { createAgent } from '@hypertask/agent-sdk/templates/replyOnly';
import { Request, Response } from 'express';
export async function createReplyOnly(
token: string,
secret: string,
onRespond: (text: string) => void
): Promise<{ app: Express.Application }> {
const { client, webhookHandler } = createAgent({ token, secret });
const app = express();
app.use(webhookHandler);
client.on('mention', async (run) => {
const response = await getBotResponse(run.prompt);
onRespond(response);
await run.respond(response);
});
client.on('chat', async (run) => {
const response = await getBotResponse(run.prompt);
onRespond(response);
await run.respond(response);
});
return { app };
}

An agent that receives assigned tickets, updates progress, and files accurate activity. Works well for triage bots, status reporters, and project workflow helpers.

templates/ticketWorker.ts
import { createAgent } from '@hypertask/agent-sdk/templates/ticketWorker';
import { Request, Response } from 'express';
export async function createTicketWorker(
token: string,
secret: string,
onAnalyze: (ticket: any) => Promise<string>
): Promise<{ app: Express.Application }> {
const { client, webhookHandler } = createAgent({ token, secret });
const app = express();
app.use(webhookHandler);
client.on('assigned', async (run) => {
await run.thought(`Analyzing ticket ${run.ticket.id}`);
const summary = await onAnalyze(run.ticket);
await run.task.comment(summary);
await run.thought('Completed analysis');
await run.respond('Analysis complete. See comment for details.');
});
return { app };
}

A bot that runs only on a cron schedule, without webhooks. Good for summaries, reports, or regular monitoring agents.

templates/scheduledBot.ts
import { createAgent } from '@hypertask/agent-sdk/templates/scheduledBot';
import { MemoryDeliveryScheduler } from '@hypertask/agent-sdk';
export async function createScheduledBot(
token: string,
secret: string,
onTick: (run: Run) => Promise<void>
): Promise<{ app: Express.Application; scheduler: MemoryDeliveryScheduler }> {
const { client, webhookHandler } = createAgent({ token, secret });
const scheduler = new MemoryDeliveryScheduler();
const app = express();
app.use(webhookHandler);
if (scheduler) {
await scheduler.schedule('0 */6 * * *', async () => {
const run = await client.createRun(COMMENT_MENTION);
await run.thought('Scheduled bot tick');
await onTick(run);
});
}
return { app, scheduler };
}
  • Signature verification — The SDK validates all incoming webhooks with HMAC signatures so you don't need to.
  • Fast acknowledgement — Always post a thought within 10 seconds after receiving mention or assigned. If the run goes stale after 5 minutes, it automatically stops.
  • Retry-safe delivery IDs — The SDK supports record-and-retry workflows so you can handle webhook delivery without duplicating actions.
  • Typed activity stream — All activity (thought, action, response, error, ask) is recorded in the thread as muted rows that look like tool calls, making the agent's reasoning visible.
  • Built-in lease management — All task helpers include heartbeat logic, so your agent never loses its claim to a ticket.
  • HTTP transport flexibility — The SDK generates a webhook handler compatible with Express, Hono, Next.js API routes, Cloudflare Workers, and plain Node.js.
  1. Create the SDK client — Call createAgent({ token, secret }). The SDK wraps your existing routes and injects signature verification.
  2. Register event handlers — Subscribe to mention, assigned, chat, and stop as needed.
  3. Handle events with a run — Each handler receives a run object with ticket, thread, and helpers.
  4. Record activities — Use run.thought, run.action, run.respond, run.error, run.ask to build the typed activity stream.
  5. Update tickets with helpers — Use run.task.move, assign, comment, update, attach to modify tickets without managing leases manually.

The SDK automatically:

  • Starts a new run on mention or assigned
  • Checks the signature on every webhook
  • Bounces the run if no activity occurs for 5 minutes
  • Records all activity in the thread when the SDK receives the webhook
If you want to…See
Configure webhooksAgent webhooks
Run agents on a scheduleSchedule an agent
Define patterns for multi-step workflowsAgent Workflows
Learn about the infrastructure powering runsAgents Dashboard

For v1, the following are out of scope:

  • OAuth marketplace install (create your agent using existing tokens)
  • Python SDK
  • Hosted runtime for client agents