Agent

Agents: hosted agents you message by name.

class Agent

A hosted agent. Agent.fromName("host", { createIfMissing: true, instructions }) is lazy; (await agent.message("hi")).text talks to it.

An account-level agent is shared: each user that messages it (via asUser or { user }) gets its own conversations. A user's own agent always talks as that user.

Attributes
idstring
originAgentOrigin | null

api for an agent made through the API, app for one built in the NoClick app (an id like node:<workflow>:<node>).

namestring
modelstring | null

The model it runs, as its harness names it (sonnet, openrouter/...).

harnessHarnessName | null

What runs it: sdk, claude_code, codex, opencode, hermes or openclaw.

modelConnectionstring | null

The connection whose key or plan it thinks with, by name (null on sdk without one). Hidden, like instructions, from a user's session reading an account agent.

instructionsstring | null
tools(string | JsonObject)[]

What it can use, as listed: refs, { tool, bind } for an operation with arguments bound and { human, tools } for a person.

canRequeststring[]

What it may ask its user to connect at run time.

userIdstring | null
workflowIdstring | null
nodeIdstring | null

An app agent's step in its workflow (null for an API agent).

workflowNamestring | null

An app agent's workflow, by name.

accessstring | null

An app agent's workflow as you hold it: owner, or editor or viewer when it was shared with you (only an owner's or an editor's takes messages).

enabledboolean | null

Whether an app agent is switched on; a disabled one takes no messages.

appUrlstring | null

Where an app agent is changed: its workflow in the NoClick app.

parentIdstring | null

The agent an ephemeral agent's budget is carved from.

ttlSnumber | null

The time to live it was created with, in seconds (null if it isn't temporary); expiresAt is when it runs out.

expiresAtDate | null

When a temporary agent expires (null if it isn't): it then stays readable, expired, for 30 days.

budgetUsdPerMonthnumber | null
regionRegionName | null

The region its sandboxes run in, fixed when it was created; null: wherever NoClick has capacity.

machineIdstring | null

Invite-only beta. The Machine its harness runs on (null: a sandbox per conversation).

createdAtDate | null
browserProfileIdstring | null

Invite-only beta. The browser profile its browser tool signs in with.

cardIdstring | null

Invite-only beta. The card it holds and pays with (null: none of its own).

volumesRecord<string, string>

The volumes its shell mounts: { path: volume id }.

memoryIdstring | null

Its own memory (agent.memory) as a Memory id, to attach to other agents.

memories{ id: string; writes: boolean }[] | null

The memories it reads besides its own, in order: each { id, writes } (null for a user's session reading an account agent).

secretIdsstring[]

The secrets in its shell's environment, in order (a later one's key wins).

timezonestring | null

The IANA timezone its turns tell the time in (null: the acting user's, else UTC).

reposJsonObject[]

The repositories cloned into its workspace: each its connection, repository, branch, path and push globs.

networkNetworkAccess | null

What its shell and code reach: true (anywhere), false (only what it needs to work) or the hosts it may reach besides, as sent.

shellboolean | null

Whether it has a shell (the code capability; false only on sdk).

statusAgentStatus | null

working, idle or expired (paused is its own field: pausing stops triggers, not work). Like the activity fields below, null for a user's session reading an account agent, whose activity is other users' turns.

lastActiveAtDate | null

When a turn of its last started or ended (null: it never ran, or hidden like status).

runningTurnsnumber | null

How many of its turns are queued, running or waiting on a person, any conversation (null: hidden like status).

childCountnumber | null

How many live (not expired) children it has (children() lists them; null: hidden like status).

jobIdstring | null

The task it was spawned with (its operation id), or null.

usedByUsedBy[]

The apps that bind it: kind (project), id, name and the binding name.

pausedboolean

Whether pause() stopped its triggers (false too for a user reading an account agent).

jobJob | null

The task it was spawned with, as a Job to wait on, or null.

triggerKindsstring[]

The kinds of its triggers (cron, webhook, event, platform, email, call); an agent with cron is an automation.

consoleUrlstring | null

This agent in the developer console (null off the hosted API).

a2aUrlstring

The A2A JSON-RPC endpoint (message/send, tasks/get); callers authenticate with a platform key as a bearer token.

memoryAgentMemory

What it remembers across conversations: list, search, read, save and delete named entries.

createstatic

static create(
  name: string,
  options: AgentCreateOptions & { instructions: string },
): Promise<Agent>

Create an agent (names are unique per account and user; a duplicate throws Conflict with existingId).

Parameters
namestringrequired
options.instructionsstringrequired
options.modelstring

The harness's own model: an OpenRouter id with the openrouter/ prefix on sdk, an alias such as sonnet on claude_code, a provider/model on opencode, hermes and openclaw; the harness's default when omitted.

options.harnessHarnessName

What runs it: sdk (the default), NoClick's own agent loop, or a coding agent in a sandbox of its own (claude_code, codex, opencode, hermes, openclaw). A new harness without a model takes that harness's default model, and each conversation carries on on it.

options.modelConnectionstring | Connection | null

The connection whose key or plan it thinks with: a Connection of a kind: "model" integration such as anthropic, or its name, in the agent's own scope (a lazy createIfMissing one is created first). Every CLI harness needs one, and it may still be pending; on sdk it's optional and lets model name anthropic/... or openai/... on your key. In fromName, null clears it (back to sdk takes harness: "sdk", modelConnection: null).

options.toolsAgentTools
options.ttlSnumber

A temporary agent: after this many seconds it's expired, taking no turns (its pending wake-ups are canceled) and readable for 30 days, then deleted.

options.budgetUsdPerMonthnumber | null

In fromName, null clears it, as browserProfile and card do.

options.canRequest(string | { name: string })[]

What it may ask its user to connect at run time (a request_connection tool): integration names (or IntegrationInfos), single "integration.operation"s, or "*". What the user connects is a grant (grants()), kept apart from this definition.

options.triggersTriggerDefinition[]

What wakes it without a message: OnWebhook, OnEvent, OnPlatformEvent, Cron and OnQueue.

options.browserProfilestring | BrowserProfile | nullinvite-only beta

Invite-only beta. The profile its browser tool signs in with (a BrowserProfile or id of its own user's, or the account's for an account agent): each conversation gets a browser of its own for a turn, a step only a person can do holds the turn awaiting_human, and its calls follow policy as browser.*.

options.cardstring | Card | nullinvite-only beta

Invite-only beta. The card it holds and pays with (a Card or id of its own scope; giving one takes the key's cards scope): a card has one agent at a time. It gets card__status and card__purchase (approve before paying: above the card's threshold the turn waits for a person, whose answer is its next turn), which policy names card.status and card.purchase, and never sees the number. A turn answering someone outside its scope, or a test run, buys nothing. A child it spawns pays with the same card only when given "card" in its tools. In update, null takes its card back.

options.volumesRecord<string, VolumeRef>

Volumes its shell mounts read-write, by absolute path, in every conversation, up to 5: { "/data": Volume.fromName("datasets") } (a Volume, an id or a name: its user's own, else the account's). Not /workspace, /root or a system folder. An sdk agent's shell sees each as the turn started and saves its writes when it ends; a coding harness's sandbox, while it's up.

options.secretsSecretRef[]

Secrets whose keys become environment variables in its shell, up to 20, a later one's key winning (a Secret, an id or a name: its user's own, else the account's; an account agent's, the account's only). A model provider's key (OPENAI_API_KEY and the like) belongs on modelConnection: a secret holding one throws InvalidRequest.

options.timezonestring | null

The IANA timezone every turn is told the date and time in; without one, the acting user's timezone, else UTC. In fromName, null clears it.

options.reposRepoCheckout[]

Repositories cloned into its workspace (/workspace/<name>) at a conversation's first turn: connection.checkout(...) through a github connection of its own scope (repo.checkout(...) is in invite-only beta), up to 10 (none with shell: false). Its git reaches those repositories only, through NoClick, with a key made for its sandbox; a push goes through only to the branches the checkout's push globs name (none: read-only), judged by NoClick on the way to the git host, since a harness's own git push is no tool call a policy could judge. gh only reads them.

options.networkNetworkAccess

What its shell and code may reach: true (anywhere, the default), false, or up to 50 hosts ("pypi.org", or "*.example.com" for a domain and its subdomains), over HTTPS on port 443 only. What it needs to work stays reachable, and false leaves only that: an sdk agent's shell reaches NoClick's git proxy when it has repos (its model and tools run on NoClick); a coding harness reaches NoClick's API, NoClick's proxy for its model on a key and for git, and on a Claude or ChatGPT plan that provider's own hosts. Its tools run on NoClick, outside the limit. Omitted, its parent's, else anywhere; the children it spawns take its. Where NoClick can't keep to a limited network (a coding harness on a key other than Anthropic, OpenAI or OpenRouter, say), it throws NotAvailable rather than widen it. In update, from its next turn.

options.shellboolean

false takes the shell (the code capability) away from an sdk agent, and from the children it spawns; a CLI harness refuses it with InvalidRequest, since its shell is the harness.

options.regionRegionName

Where its sandboxes run (regions()), for good: a coding harness runs there whole, and an sdk agent's shell does while its loop runs in NoClick's own service. Omitted, its parent's, else your account's default region, else wherever NoClick has capacity. An existing agent elsewhere makes fromName throw Conflict naming its region.

options.machinestring | Machine | nullinvite-only beta

Invite-only beta. The always-on Machine (or its id) its harness runs on instead of a sandbox per conversation: nothing reaped when it's quiet, no per-minute sandbox charge, in the machine's region. A coding harness there reaches its model only through NoClick's credential proxy, so its modelConnection holds an Anthropic, OpenAI or OpenRouter key (a Claude or ChatGPT plan throws NotAvailable); a machine runs at most 50 agents. In update, null moves it back to sandboxes.

options.memoriesMemoryRef[]

The Memorys it reads besides its own (agent.memory), in order, up to 10: a Memory, its id or name (its user's own, else the account's), or another agent's memory. Each is read-only to it unless given as memory.writable(); a user's agent reads the account's memories but never writes them, and never another user's. Every turn starts with each entry's name and description, its own memory's first.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

options.parentstring | Agent

The parent agent an ephemeral agent's budget is carved from.

Returns

The new agent, loaded.

fromNamestatic

static fromName(
  name: string,
  options?: AgentCreateOptions & { createIfMissing?: boolean },
): Agent

A lazy reference to the agent called name for the current (or given) user: inside asUser only that user's own agent, never an account agent of the same name. With createIfMissing your code is the definition: it's created on first use, and an existing agent whose instructions, model, modelConnection, tools, canRequest or budget differ is updated to match (the grants its user gave it are kept). A field left out is never changed; null clears modelConnection, budgetUsdPerMonth, browserProfile or card, as update does.

Parameters
namestringrequired
options.createIfMissingboolean
options.instructionsstring
options.modelstring

The harness's own model: an OpenRouter id with the openrouter/ prefix on sdk, an alias such as sonnet on claude_code, a provider/model on opencode, hermes and openclaw; the harness's default when omitted.

options.harnessHarnessName

What runs it: sdk (the default), NoClick's own agent loop, or a coding agent in a sandbox of its own (claude_code, codex, opencode, hermes, openclaw). A new harness without a model takes that harness's default model, and each conversation carries on on it.

options.modelConnectionstring | Connection | null

The connection whose key or plan it thinks with: a Connection of a kind: "model" integration such as anthropic, or its name, in the agent's own scope (a lazy createIfMissing one is created first). Every CLI harness needs one, and it may still be pending; on sdk it's optional and lets model name anthropic/... or openai/... on your key. In fromName, null clears it (back to sdk takes harness: "sdk", modelConnection: null).

(omit to leave it unchanged)
options.toolsAgentTools
options.ttlSnumber

A temporary agent: after this many seconds it's expired, taking no turns (its pending wake-ups are canceled) and readable for 30 days, then deleted.

options.budgetUsdPerMonthnumber | null

In fromName, null clears it, as browserProfile and card do.

(omit to leave it unchanged)
options.canRequest(string | { name: string })[]

What it may ask its user to connect at run time (a request_connection tool): integration names (or IntegrationInfos), single "integration.operation"s, or "*". What the user connects is a grant (grants()), kept apart from this definition.

options.triggersTriggerDefinition[]

What wakes it without a message: OnWebhook, OnEvent, OnPlatformEvent, Cron and OnQueue.

options.browserProfilestring | BrowserProfile | nullinvite-only beta

Invite-only beta. The profile its browser tool signs in with (a BrowserProfile or id of its own user's, or the account's for an account agent): each conversation gets a browser of its own for a turn, a step only a person can do holds the turn awaiting_human, and its calls follow policy as browser.*.

(omit to leave it unchanged)
options.cardstring | Card | nullinvite-only beta

Invite-only beta. The card it holds and pays with (a Card or id of its own scope; giving one takes the key's cards scope): a card has one agent at a time. It gets card__status and card__purchase (approve before paying: above the card's threshold the turn waits for a person, whose answer is its next turn), which policy names card.status and card.purchase, and never sees the number. A turn answering someone outside its scope, or a test run, buys nothing. A child it spawns pays with the same card only when given "card" in its tools. In update, null takes its card back.

(omit to leave it unchanged)
options.volumesRecord<string, VolumeRef>

Volumes its shell mounts read-write, by absolute path, in every conversation, up to 5: { "/data": Volume.fromName("datasets") } (a Volume, an id or a name: its user's own, else the account's). Not /workspace, /root or a system folder. An sdk agent's shell sees each as the turn started and saves its writes when it ends; a coding harness's sandbox, while it's up.

options.secretsSecretRef[]

Secrets whose keys become environment variables in its shell, up to 20, a later one's key winning (a Secret, an id or a name: its user's own, else the account's; an account agent's, the account's only). A model provider's key (OPENAI_API_KEY and the like) belongs on modelConnection: a secret holding one throws InvalidRequest.

options.timezonestring | null

The IANA timezone every turn is told the date and time in; without one, the acting user's timezone, else UTC. In fromName, null clears it.

(omit to leave it unchanged)
options.reposRepoCheckout[]

Repositories cloned into its workspace (/workspace/<name>) at a conversation's first turn: connection.checkout(...) through a github connection of its own scope (repo.checkout(...) is in invite-only beta), up to 10 (none with shell: false). Its git reaches those repositories only, through NoClick, with a key made for its sandbox; a push goes through only to the branches the checkout's push globs name (none: read-only), judged by NoClick on the way to the git host, since a harness's own git push is no tool call a policy could judge. gh only reads them.

options.networkNetworkAccess

What its shell and code may reach: true (anywhere, the default), false, or up to 50 hosts ("pypi.org", or "*.example.com" for a domain and its subdomains), over HTTPS on port 443 only. What it needs to work stays reachable, and false leaves only that: an sdk agent's shell reaches NoClick's git proxy when it has repos (its model and tools run on NoClick); a coding harness reaches NoClick's API, NoClick's proxy for its model on a key and for git, and on a Claude or ChatGPT plan that provider's own hosts. Its tools run on NoClick, outside the limit. Omitted, its parent's, else anywhere; the children it spawns take its. Where NoClick can't keep to a limited network (a coding harness on a key other than Anthropic, OpenAI or OpenRouter, say), it throws NotAvailable rather than widen it. In update, from its next turn.

options.shellboolean

false takes the shell (the code capability) away from an sdk agent, and from the children it spawns; a CLI harness refuses it with InvalidRequest, since its shell is the harness.

options.regionRegionName

Where its sandboxes run (regions()), for good: a coding harness runs there whole, and an sdk agent's shell does while its loop runs in NoClick's own service. Omitted, its parent's, else your account's default region, else wherever NoClick has capacity. An existing agent elsewhere makes fromName throw Conflict naming its region.

options.machinestring | Machine | nullinvite-only beta

Invite-only beta. The always-on Machine (or its id) its harness runs on instead of a sandbox per conversation: nothing reaped when it's quiet, no per-minute sandbox charge, in the machine's region. A coding harness there reaches its model only through NoClick's credential proxy, so its modelConnection holds an Anthropic, OpenAI or OpenRouter key (a Claude or ChatGPT plan throws NotAvailable); a machine runs at most 50 agents. In update, null moves it back to sandboxes.

options.memoriesMemoryRef[]

The Memorys it reads besides its own (agent.memory), in order, up to 10: a Memory, its id or name (its user's own, else the account's), or another agent's memory. Each is read-only to it unless given as memory.writable(); a user's agent reads the account's memories but never writes them, and never another user's. Every turn starts with each entry's name and description, its own memory's first.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

options.parentstring | Agent

The parent agent an ephemeral agent's budget is carved from.

Returns

An agent that loads (or is created, or brought in step with your definition) the first time it's used. Nothing is sent yet.

fromIdstatic

static fromId(agentId: string, options?: CallOptions): Agent

A lazy reference to an agent by NoClick id.

Parameters
agentIdstringrequired
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
Returns

An agent that loads the first time it's used. Nothing is sent yet.

getstatic

static get(agentId: string, options?: CallOptions): Promise<Agent>

Load an agent by NoClick id now; an unknown id raises noclick.NotFound.

Parameters
agentIdstringrequired
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The agent, loaded.

liststatic

static list(options?: AgentListOptions & { limit?: number }): Promise<Agent[]>

The agents the current user can message: inside asUser, that user's own agents and the account's (which the user can message but not change; their userId is null), so a name may match one of each; outside it, the account's. userFilter lists exactly whose agents instead. Expired agents are listed for the 30 days they're kept; status, activeSince, parent, temporary and harness filter, and order: "last_active" reads a column the turn runner stamps, on an index of its own.

After the account's API agents come the ones built in the NoClick app, which are the account's too (origin: "api" or "app" lists only one kind); only name and harness apply to them, and the other filters leave them out. send and message reach them; what they are is changed in the app.

for (const agent of await Agent.list({ origin: "app" })) console.log(agent.name, agent.workflowName, agent.appUrl);
Parameters
options.namestring
options.statusAgentStatus

Only agents with this status.

options.activeSinceDate | string

Only agents with a turn since then.

options.parentstring | Agent

Only the children of this agent (an Agent or id).

options.temporaryboolean

true: only agents with a ttlS; false: only agents without one.

options.harnessHarnessName

Only agents on this harness.

options.order(typeof AGENT_ORDERS)[number]

created (the default: newest first) or last_active (most recently active first, those that never ran last).

options.originAgentOrigin

Only agents made through the API (api) or built in the NoClick app (app).

options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Every matching agent, newest first (or most recently active first), fetched page by page.

listPagestatic

static listPage(options?: AgentListOptions & PageOptions): Promise<Page<Agent>>

One page of agents; pass nextCursor back as cursor. Takes list's filters.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.namestring
options.statusAgentStatus

Only agents with this status.

options.activeSinceDate | string

Only agents with a turn since then.

options.parentstring | Agent

Only the children of this agent (an Agent or id).

options.temporaryboolean

true: only agents with a ttlS; false: only agents without one.

options.harnessHarnessName

Only agents on this harness.

options.order(typeof AGENT_ORDERS)[number]

created (the default: newest first) or last_active (most recently active first, those that never ran last).

options.originAgentOrigin

Only agents made through the API (api) or built in the NoClick app (app).

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A page whose data holds the agents and whose next_cursor is None on the last page.

harnessesstatic

static harnesses(options?: { client?: NoClick }): Promise<HarnessInfo[]>

What can run an agent, each with its default model, whether it needs a modelConnection and which model providers serve it; models() on one searches the models it offers. On a CLI harness a reply arrives whole, a conversation's first turn starts its sandbox (warm about a minute between turns), and the sandbox's uptime is billed.

const codex = (await Agent.harnesses()).find((h) => h.name === "codex");
const models = await codex?.models({ search: "gpt-5" });
Parameters
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Each harness's name (what harness= takes) and default_model, whether it needs a model_connection and which model providers' integrations serve it, whether its reply streams (streaming) and whether its shell is built in. models() on one searches the models it offers.

harnessInfostatic

static harnessInfo(
  name: string,
  options?: { client?: NoClick },
): Promise<HarnessInfo>

One of harnesses() by the name harness takes; an unknown name throws NotFound, naming the ones there are.

const opencode = await Agent.harnessInfo("opencode");
Parameters
namestringrequired
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The harness: its default_model, whether it needs a model_connection, the model providers' integrations that serve it, and models() to search what it offers.

upload

upload(file: FileInput, options?: UploadOptions): Promise<Attachment>

Store a file to send this agent with a message, kept as an account file capped as those are: 10 MB an image (JPEG, PNG, WebP or GIF), 15 MB a document, 20 MB audio or video. Send it with message(text, { files: [attachment] }); a file is sent once.

Parameters
fileFileInputrequired
options.namestring

The file's name (a File has its own).

options.mimeTypestring

Its type (a Blob has its own; else read from the name).

options.voiceboolean

A recorded voice clip (audio).

options.peaksnumber[]

A voice clip's waveform: loudness 0-1, at most 64 numbers.

Returns

The attachment; send it with message(files=[...]). An upload is sent once; sent, it's one of the account's files (noclick.attachments()), which the account sends again.

send

send(
  text: string,
  options?: {
    conversation?: string | null;
    files?: (Attachment | string)[];
    user?: UserOption;
  },
): Promise<Operation<AgentReply>>

Start a turn without waiting; wait() resolves to the AgentReply. files go with it, as message sends them.

Parameters
textstringrequired
options.conversationstring | null
options.files(Attachment | string)[]
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The turn's operation, started. Keep its id to pick the reply up later, from anywhere.

message

message(
  text: string,
  options?: {
    conversation?: string | null;
    files?: (Attachment | string)[];
    timeoutS?: number;
    user?: UserOption;
  },
): Promise<AgentReply>

Send text and wait for the reply. Pass the reply's conversation back to continue the thread. files (at most 100) are attachments from upload, or their ids: the turn reads them as the agent's media digest does, a document's text, a voice clip's transcript, an image as an image.

Parameters
textstringrequired
options.conversationstring | null
options.files(Attachment | string)[]
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
options.timeoutSnumber
Returns

The reply: its text, the conversation it belongs to and the tool_calls the turn made.

history

history(
  conversation: string,
  options?: { user?: UserOption },
): Promise<Message[]>

The messages of one conversation, oldest first: each with its role, text, the files it carried, how it arrived (via, for a text, a call or an email) and, a reply, its toolCalls; a note has its data.

Parameters
conversationstringrequired
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

Its messages, each with its role, text, created_at, the files it carried, how it arrived (via, for a text, a call or an email) and, a reply, the tool_calls its turn made; a note has its data.

note

note(
  conversation: string,
  text: string,
  options?: { data?: JsonObject; key?: string; user?: UserOption },
): Promise<boolean>

Add a line to a conversation without starting a turn: it shows in history and watch as a note with its data (JSON, at most 4,096 bytes), and the agent reads both when its next turn starts, once. A key adds it once: resolves to false when a note with that key already was.

await support.note("ticket-1841", "Ada upgraded to the Pro plan.", { data: { plan: "pro" }, key: "plan:pro" });
Parameters
conversationstringrequired
textstringrequired
options.dataJsonObject
options.keystring
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

True when it was added, False when a note with key already was.

conversations

conversations(
  options?: ReadOptions & { limit?: number },
): Promise<Conversation[]>

Its conversations, most recent first (the current user's, or those userFilter covers). userFilter reads across users without the user header, which only the signed-in owner may do on a user's own agent; with a secret key, read such an agent's threads without it.

Parameters
options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick
Returns

Every matching conversation (or the first limit), fetched page by page. cost_usd is None for a thread with no recorded turns.

conversationsPage

conversationsPage(
  options?: ReadOptions & PageOptions,
): Promise<Page<Conversation>>

One page of its conversations; pass nextCursor back as cursor.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick
Returns

A page whose data holds the conversations and whose next_cursor is None on the last page.

handBack

handBack(conversation: string, options?: { user?: UserOption }): Promise<void>

Give a conversation back to the agent after it handed it to a person (its hand_off tool). The person's replies stay in its history, and the agent answers again from the next message. The person can hand it back from their page too.

Parameters
conversationstringrequired
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)

spawn

spawn(task: string, options?: SpawnOptions): Promise<Agent>

Make a child for one task and start it at once. The child lives where its parent does, on the parent's harness, model and model connection unless told otherwise, and gets only tools its parent has. child.job is the task: it runs while the child works on it and finishes when the child's conversation goes quiet. updates are when NoClick makes the child report ("done" always); every update wakes the parent in conversation, and those that come while it's busy arrive together. An agent has up to 20 live children, 3 levels below an agent with no parent. Agent.create({ parent }) still makes a child without starting it.

Parameters
taskstringrequired
options.updatesUpdateSpec[]

When NoClick makes the child report, beside "done" (always on): "blocked", new Before(...), new Every(...).

options.conversationstring

The parent's conversation its updates wake; without one they wake nobody and wait on the job.

options.instructionsstring

The child's standing instructions: what its updates should say, and when to reach out freely.

options.toolsAgentTools

Some of its parent's tools (it gets none of them otherwise); a tool its parent lacks is refused. "card" gives it the card its parent pays with.

options.budgetUsdnumber

Its budget, carved from its parent's.

options.ttlSnumber

It expires this many seconds after it's made.

options.modelstring

The parent's model when omitted.

options.harnessHarnessName

The parent's harness when omitted.

options.modelConnectionstring | Connection

The parent's model connection when omitted.

options.namestring

<parent>-<8 hex> when omitted.

options.userUserOption

Whose conversation conversation is (an account parent talking to a user: that user's thread).

(defaults to the current user)
Returns

The child, loaded, with parent_id set to this agent and job its running task.

children

children(options?: { status?: AgentStatus; limit?: number }): Promise<Agent[]>

Its children, newest first (expired ones too, for their 30 days): Agent.list({ parent }), read where it lives.

Parameters
options.statusAgentStatus
options.limitnumber

Return at most this many.

Returns

Each child with its status, last_active_at, running_turns and, if spawn made it, the job it was started with.

jobs

jobs(options?: JobFilters): Promise<Job[]>

The jobs it started, newest first: the tasks of the children it spawned, and the messages it sent with its agents tools (whose only update is done).

Parameters
options.statusOperationStatus | "live" | readonly (OperationStatus | "live")[]

Statuses, or "live" for every non-terminal one.

options.kind"task" | "message"

task (spawned), or message (sent with its agents tools).

options.agentstring | Agent

The agent doing the work (an Agent or id).

options.conversationstring

The parent's conversation that started them.

options.limitnumber

Return at most this many.

Returns

Every matching job (or the first limit), newest first, each with its status, step and latest_update; wait() on one gives its reply.

ask

ask(
  question: string,
  options?: {
    conversation?: string;
    interject?: boolean;
    timeoutS?: number;
    user?: UserOption;
  },
): Promise<AgentReply>

Ask it something without stopping it. By default its model answers from a snapshot of the conversation as it stands, with no tools; the question and answer aren't added to the conversation, and its running turn carries on untouched (an agent.ask operation, billed like a short turn). On a coding harness the snapshot holds the conversation to its last finished turn plus the NoClick tool calls of the running one; its own shell commands and file edits arrive when the turn ends. An agent on a Claude or ChatGPT plan rejects with NotAvailable (answering in a one-off harness session is in invite-only beta). interject: true joins the running turn instead (the harness's own steering; on sdk, before its next model call): the agent sees the question, may change course, and the reply that turn ends with comes back; with nothing running it's an ordinary message. conversation defaults to a spawned child's task, else the one it last worked in.

Parameters
questionstringrequired
options.conversationstring
options.interjectboolean
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
options.timeoutSnumber
Returns

The answer as an AgentReply; with interject, the reply the turn it joined ended with.

a2aCard

a2aCard(): Promise<JsonObject>

The agent's A2A agent card (the JSON other agents discover it by): its name, its JSON-RPC url and the skills it offers.

Returns

The card as a dict: the agent's name, its JSON-RPC url and the skills it offers.

update

update(
  changes: Omit<AgentFields, "modelConnection"> & { name?: string; budgetUsdPerMonth?: number | null; modelConnection?: string | Connection | null; } & Pick<AgentCreateOptions, "timezone" | "repos" | "network" | "shell" | "card" | "machine" | "memories">,
): Promise<this>

Change fields; returns the updated agent. A new harness without a model takes that harness's default model; modelConnection: null removes an sdk agent's own model key.

Parameters
changesOmit<AgentFields, "modelConnection"> & { name?: string; budgetUsdPerMonth?: number | null; modelConnection?: string | Connection | null; } & Pick<AgentCreateOptions, "timezone" | "repos" | "network" | "shell" | "card" | "machine" | "memories">required
Returns

This agent, updated. A field you leave out is unchanged, and changes apply from its next turn.

grants

grants(): Promise<AgentGrant[]>

The connections its user gave it at run time (requested or active), oldest first.

Returns

Each grant with the connection it names, its integration, its status and the operations it covers (None: every one).

revokeGrant

revokeGrant(grant: string | AgentGrant): Promise<void>

Take back a grant (an AgentGrant or its id): its tools leave the agent; the connection stays the user's.

Parameters
grantstring | AgentGrantrequired

delete

delete(): Promise<TrashItem>

Delete the agent and its sub-agents: they go to the trash, restorable for 30 days (pending wake-ups and jobs end now). Returns its TrashItem.

Returns

Its TrashItem: restore() brings it and its sub-agents back.

wake

wake(conversation: string, options: WakeOptions): Promise<Wakeup>

Wake it later in conversation: at a moment (at), after a while (afterS), when an operation reaches a terminal status or a platform event happens (when, narrowed by filters), or at each time of a schedule (every, a Cron: a routine, until it's canceled). Then the conversation takes a turn whose message is the note, followed by what woke it; a running turn there goes first. Durable, delivered once, billed and capped like any turn; one the account can't pay for fails. A recurring one stays pending, due at its schedule's next time after each turn, so times it missed fold into one turn. An agent holds up to 100 pending and 20 recurring; a time wake-up is 1 minute to 365 days ahead, a schedule comes round at most every minute (every 15 for one the agent sets itself), and a conversation's are delivered at least a minute apart. Every agent can also set, list, change and cancel its own with its wake_me, list_wakeups and cancel_wakeup tools. A channel's conversation (channel:<its id>) rejects with InvalidRequest, as message does: only the channel starts turns there.

await assistant.wake("briefing", { every: new Cron("0 8 * * 1-5", { tz: "user" }),
  note: "Brief me on today's calendar and anything urgent in my inbox." });
Parameters
conversationstringrequired
options.notestringrequired

What the turn is told, 1 to 4,000 characters.

options.atDate | string

A moment: a Date, or an ISO 8601 string with its offset.

options.whenOperation<unknown> | string

When an operation reaches a terminal status (a Job, a HumanRequest, a ConnectLink, ...; one that has wakes it at once), or a NoClick event type such as "connection.connected" (* matches the rest of a name): the first matching event after it was set wakes it. A user's conversation hears that user's events; one of your account's own hears every event, your users' included.

options.filtersJsonObject

With an event when: dotted paths into the event's data that must equal these values.

options.everyCron

A routine: it wakes the conversation at each time of this Cron until it's canceled (tz: "user" follows the conversation's user). The note is what it's told, so the Cron takes no message.

options.userUserOption

Whose conversation it is, as message() takes it.

(defaults to the current user)
options.afterSnumber

This many seconds from now.

Returns

The wake-up, pending; update() changes it, cancel() calls it off.

wakeups

wakeups(
  options?: ReadOptions & {
    conversation?: string;
    status?: WakeupStatus;
    limit?: number;
  },
): Promise<Wakeup[]>

Its wake-ups in the acting user's conversations, newest first, or in those of the users userFilter covers (ALL_USERS, NO_USER, a User or your id for one; read without the user header, as conversations does): those your code and the agent set, and NoClick's own (a job's update, a connect link it asked for being done, a decided approval); conversation and status narrow them. Each one's cancel() acts in its own thread.

Parameters
options.statusWakeupStatus
options.limitnumber

Return at most this many.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.clientNoClick
options.conversationstring
Returns

Every matching wake-up (or the first limit), newest first, each with its source, when it's due (at) or what it waits for (when), whose thread it's in (user_id) and, once delivered, the turn it started. cancel() acts in that wake-up's own thread.

triggers

triggers(): Promise<AgentTrigger[]>

What wakes it besides a message: its schedules, webhooks, app events, NoClick events and queues, and the inboxes and phone numbers that hand it mail and calls.

Returns

Each trigger with its kind, its spec, its status (paused while the agent is), the url a webhook listens at, when a schedule's next_run is and when it last_fired_at. An error says why one can't fire.

addTrigger

addTrigger(trigger: TriggerDefinition): Promise<AgentTrigger>

Add a trigger (up to 20): an OnWebhook (its url is where to POST), an OnEvent (error until its connection is connected) or a Cron (its nextRun says when it fires; paused while the agent is). An agent defined with fromName({ createIfMissing, triggers }) gets its list from your code instead, and loses one added here the next time that code runs.

Parameters
triggerTriggerDefinitionrequired
Returns

The trigger as added; a webhook's url is where to send its POSTs. An event trigger whose connection isn't connected yet is error until it is.

removeTrigger

removeTrigger(trigger: AgentTrigger | string | TriggerDefinition): Promise<void>

Remove a trigger: an AgentTrigger (or its id), or the definition you added (NotFound if the agent has none like it): an OnWebhook by its name alone, as names are unique on an agent. Mail and call triggers are changed on their inbox or number.

Parameters
triggerAgentTrigger | string | TriggerDefinitionrequired

inboxes

inboxes(): Promise<Inbox[]>

The inboxes whose mail wakes it (created or updated with it as their agent).

Returns

Every such inbox, newest first, each with its address.

pause

pause(): Promise<this>

Stop every trigger from waking it: scheduled runs are skipped (not made up later), webhook calls are refused with 409 so their sender can retry, and app events, mail and calls that arrive meanwhile don't wake it. Messages your code sends still run, and so do calls under way.

Returns

This agent, with paused true.

resume

resume(): Promise<this>

Let its triggers wake it again, including one that stopped after failing; a schedule picks up at its next run.

Returns

This agent, with paused false.

workspace

workspace(conversation: string, options?: { user?: UserOption }): AgentWorkspace

The files it works on in one conversation. Sends nothing yet.

Parameters
conversationstringrequired
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The conversation's workspace, whose files, read, write and url reach its files.

share

share(): Promise<ShareLink>

Turn on its public chat page, or read it if it's on: anyone with the link can talk to the agent, no sign-in, each visitor in conversations of their own. Visitors' turns bill to you.

Returns

The link: its url, and disable() and rotate() to turn it off or change it.

stream

async *stream(
  text: string,
  options?: {
    conversation?: string | null;
    files?: (Attachment | string)[];
    user?: UserOption;
    signal?: AbortSignal;
  },
): AsyncGenerator<AgentEvent>

Send text (with any files, as message sends them) and watch the turn as it happens: the reply as it's written, each tool call and its result, each file, approval and long action, then a done event carrying the whole AgentReply. The same turn as message, billed the same; a turn that fails throws its error.

Parameters
textstringrequired
options.conversationstring | null
options.files(Attachment | string)[]
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
options.signalAbortSignal
Returns

AgentEvent values in order, ending with one whose type is done and whose reply is the AgentReply. A turn that fails raises its error instead.

watch

async *watch(
  conversation: string,
  options?: { user?: UserOption; signal?: AbortSignal },
): AsyncGenerator<AgentEvent>

Follow one conversation live, whoever moves it: turns a trigger, an answered ask or an approved held call started, messages sent from another client or session, and a person's replies after a hand-off. Yields message (a whole message, with its role, files and, a reply, its toolCalls), text, tool_call (held names the approval when policy holds it), tool_result, file, approval and operation (from its "noclick" tools) and status events. Your own turns show up too; tell them apart by operationId. It runs until you stop reading or abort signal.

Parameters
conversationstringrequired
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
options.signalAbortSignal
Returns

AgentEvent values as they happen: message (a whole message, with its role: user, assistant or person, and its files), text as a reply is written, tool_call (held names the approval when policy holds it), tool_result, file, approval and operation (from its "noclick" tools), and status when the conversation starts waiting on a person, is handed off or becomes active.

rehearse

rehearse(
  message: string,
  options?: { scenario?: string; user?: UserOption },
): Promise<Operation<Rehearsal>>

A test run: a real turn of this agent where a simulated world answers every tool call, so nothing is sent, no account is touched and its connections needn't be connected yet (its model connection must be). scenario says what that world is like; without one it's an ordinary busy day. Billed like a turn and counted toward the agent's budget; up to 10 runs per account queued or running at once (QuotaExceeded past that). wait() resolves to the Rehearsal.

Parameters
messagestringrequired
options.scenariostring
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The run's operation (kind agent.rehearse); .wait() gives the Rehearsal: the reply, and the tool_calls it made with what the world answered.

AgentGrant

interface AgentGrant

A connection the agent's user gave it at run time (it asked with its request_connection tool, within canRequest). status is requested until the user connects, then active; operations null means every operation.

Attributes
idstring
connectionstring
integrationstring
operationsstring[] | null
status"requested" | "active"
reasonstring | null
conversationstring | null
createdAtDate | null
grantedAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

AgentReply

interface AgentReply

The agent's answer to one message.

Attributes
textstring
conversationstring | null

Pass back as conversation to continue the same thread.

toolCallsJsonObject[]

The turn's tool calls, each {tool, arguments, result, is_error, created_at} as history() shows a reply's (a failed call's result is its error); a coding harness's own steps add source: "harness".

operationIdstring | null
rawJsonObject

The response JSON exactly as the API sent it.

modelUsageModelUsage | null

The turn's model calls on your own key or plan (null on NoClick's key, whose cost is its cost_usd).

Conversation

interface Conversation

One thread with an agent (a user's, or the account's own).

Attributes
conversationstring

Pass as conversation to continue it, or to history().

userIdstring | null
titlestring | null
previewstring | null
turnsnumber | null
costUsdnumber | null
lastActivityDate | null
rawJsonObject

The response JSON exactly as the API sent it.

statusConversationStatus | null

active, awaiting_human (a turn waits on a person: its question, a held call, a sign-in) or handed_off.

handedOffTostring | null

Who a handed_off conversation is with: the person's email or phone.

modelUsageModelUsage | null

Its model calls on your own key or plan, all turns together (null on NoClick's key).

Message

interface Message

One message of a conversation: its role is user, assistant, person (someone it was handed off to) or note (a line added with agent.note, with its data).

Attributes
rolestring
textstring
createdAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

filesAttachment[]

The files it carried (a user message's, sent with files).

toolCallsJsonObject[]

A reply's tool calls: each {tool, arguments, result, is_error, created_at}, as its turn's tool_call and tool_result events showed it (arguments cut short are {_truncated: true}).

viaMessageVia | null

How a user message arrived when not through the API (null otherwise).

dataJsonObject | null

A note's data, as agent.note added it.

triggerMessageTrigger | null

What started the turn of a user message no person sent (null for one someone sent).

reasoningReasoningLine[]

A reply's reasoning, as its turn's reasoning events showed it.

HarnessInfo

interface HarnessInfo

What can run an agent: one of Agent.harnesses(). sdk is NoClick's own agent loop; the others are coding agents that run in a sandbox of their own, with a shell and files, and think with the key or plan of a modelConnection. models() searches the models it offers.

Attributes
nameHarnessName

What harness takes.

labelstring | null
versionstring | null

The version NoClick runs (null for sdk).

defaultModelstring

The model an agent on it gets when you give none.

customModelsboolean

Whether model also takes models models() doesn't offer.

modelConnection"required" | "optional"

required for every CLI harness, optional for sdk.

integrationsstring[]

The model providers (kind: "model" integrations) whose connection it can think with.

streaming"tokens" | "final"

tokens when the reply streams as it's written, final when it arrives whole.

shell"built_in" | "code_capability"

built_in when it has its own shell and file tools, code_capability when its shell is the code tool.

notesstring[]

What to know before choosing it (a model that needs a particular key, say).

rawJsonObject

The response JSON exactly as the API sent it.

models

models(options?: { search?: string; limit?: number }): Promise<HarnessModel[]>

The models it offers, its default first: the first limit (50; at most 200), or those whose id or label contains search (case-insensitive). A search after a few quiet minutes reads the providers' lists afresh, so it can take seconds.

const models = await opencode.models({ search: "claude", limit: 10 });
Parameters
options.limitnumber

Return at most this many.

options.searchstring
Returns

Each model's id (what model= takes) and label. A harness whose custom_models is True also runs ids it doesn't list.

HarnessModel

interface HarnessModel

A model a harness offers, by the id its model takes.

Attributes
idstring
labelstring | null

ModelUsage

interface ModelUsage

What an agent's model calls on your own key or plan (its modelConnection) used: tokens in (cachedTokens of them read from the provider's cache), tokens out, and what they come to in US dollars at the provider's list price. NoClick doesn't bill these calls; this is how you see them. A coding harness on a plan counts what it reports, priced as if it ran on a key.

Attributes
inputTokensnumber
outputTokensnumber
cachedTokensnumber
usdnumber
rawJsonObject

The response JSON exactly as the API sent it.

AgentMemory

class AgentMemory

agent.memory: named notes the agent keeps across conversations. Every turn starts with each entry's name and description; the agent reads a body when it needs one, and saves what it learns. Your code can seed, read, correct and forget entries the same way.

An account agent keeps two layers: entries saved outside asUser are the account's, read in every user's conversations, and what it learns while talking to a user is that user's alone. A user's own agent has one memory, the user's. The agent changes the account's entries only in conversations your code has with it outside asUser, and only reads its memory when it answers someone outside your account (an inbox's sender, a caller, a visitor to its share link). A long conversation also keeps its checkpoint here, in that conversation's layer (MemoryEntry.conversation).

It's a Memory (its id is agent.memoryId) that goes with the agent: another agent of its scope can read it too, with memories: [agent.memory], and named memories (Memory) are attached the same way.

list

list(options?: { user?: UserOption }): Promise<MemoryEntry[]>

The entries of one layer (the account's outside asUser, else the user's), by name, without their content.

Parameters
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

Each entry's name, description, version and when it last changed, by name; content is None here, so read an entry for its body.

search

search(
  query: string,
  options?: { limit?: number; user?: UserOption },
): Promise<MemoryEntry[]>

Search what the agent remembers in a scope, the way the agent does (a user's entries and the account's): entries whose name, description or content holds any of the query's words (refund also finds refunds), or whose name or description holds the query; best first, with content (10 unless limit says otherwise, at most 100).

Parameters
querystringrequired
options.limitnumber

Return at most this many.

options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The best matches first (10 unless limit says otherwise, at most 100), each with its content and user_id (None for the account's entries).

read

read(name: string, options?: { user?: UserOption }): Promise<MemoryEntry>

One entry in full; a name with no entry throws NotFound.

Parameters
namestringrequired
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The entry with its content and the version to pass back when you change it.

save

save(
  name: string,
  content: string,
  options?: { description?: string; version?: number; user?: UserOption },
): Promise<MemoryEntry>

Write an entry, creating it if the name is new. description is the line the agent sees every turn (required for a new entry, kept when omitted). With version the save only lands if the entry is still at that version, else Conflict; without it, it replaces whatever is there.

Parameters
namestringrequired
contentstringrequired
options.descriptionstring
options.versionnumber
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

The entry as saved, with its new version.

delete

delete(
  name: string,
  options?: { version?: number; user?: UserOption },
): Promise<void>

Forget an entry; with version, only if it is still at that version (else Conflict).

Parameters
namestringrequired
options.versionnumber
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)

entries

entries(options?: { user?: UserOption }): Promise<MemoryEntry[]>

list, as Memory calls it.

Parameters
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns

Each entry's name, description and version, by name, without its content.

forget

forget(
  name: string,
  options?: { version?: number; user?: UserOption },
): Promise<void>

delete, as Memory calls it.

Parameters
namestringrequired
options.versionnumber
options.userUserOption

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)

MemoryEntry

interface MemoryEntry

One named note in an agent's memory. version goes up with every save; pass the one you read back to save or delete so you never overwrite a change the agent made since. content is null in a listing (read loads it). updatedBy is agent, api or console.

conversation is set on a conversation's checkpoint: a long conversation keeps its older history folded into one entry, named context. and a hash, which its turns read in place of that history. Read it to see what the agent carries forward; an edit wins over the next summary, and deleting it forgets that history for good. The agent never sees it outside that conversation.

Attributes
namestring
descriptionstring
contentstring | null
versionnumber
updatedAtDate | null
updatedBy"agent" | "api" | "console" | null
userIdstring | null
conversationstring | null
rawJsonObject

The response JSON exactly as the API sent it.

AgentWorkspace

class AgentWorkspace

The files an agent works on in one conversation (agent.workspace(conversation)): what it writes with its shell or its tools, and what you put there for it. Every turn of that conversation sees the same files under /workspace; each user's thread with an account agent has its own. (A Workspace is something else: channels and their members.)

Attributes
conversationstring

The conversation whose files these are.

files

files(): Promise<WorkspaceFile[]>

Every file in the workspace, each with a download url (empty until the agent writes one).

Returns

Each file's path (relative to /workspace), size, when it last changed and a download url. An empty list for a conversation whose agent hasn't written anything.

read

read(path: string): Promise<Uint8Array>

Read one file's bytes; a missing file throws NotFound.

Parameters
pathstringrequired
Returns

The file's bytes, exactly as stored; decode text yourself.

write

write(path: string, data: string | Uint8Array): Promise<WorkspaceFile>

Put a file in the workspace (text as UTF-8), replacing one at that path; at most 100 MB. A coding harness's sandbox stays up between turns and sees it once it starts again.

Parameters
pathstringrequired
datastring | Uint8Arrayrequired
Returns

The file as stored, with its download url.

url

url(path: string, options?: { expiresInS?: number }): Promise<string>

A link that downloads one file without a key, for expiresInS seconds (an hour by default, a day at most).

Parameters
pathstringrequired
options.expiresInSnumber
Returns

The link; it works for expires_in_s seconds (an hour by default, a day at most).

WorkspaceFile

interface WorkspaceFile

A file in a conversation's workspace; url downloads it without a key for about an hour.

Attributes
pathstring

Relative to /workspace.

sizeBytesnumber
modifiedAtDate | null
urlstring | null
rawJsonObject

The response JSON exactly as the API sent it.

AgentEvent

interface AgentEvent

One moment of a streamed turn or a watched conversation. type is text (text is the next piece of the reply), tool_call (tool, its wire name like gmail__send_email_message, and its arguments; held when policy holds it for a person), tool_result (tool, its result: the start of what it returned, up to 500 characters, or its error; and whether it isError), file (a file the message carried, role user, or the turn made, assistant), reasoning (text is one short line of what the model is thinking, the title of a section of its reasoning, sent as it completes), status (compacting while a long conversation's older history is summarized, then compacted), approval (its "noclick" tools held a purchase or a deletion for the account's owner: the approval), operation (they started a long action: the operation, which comes again with its progress each time the work reports some and once more when it ends) or done (reply is the whole AgentReply, as message resolves to). agent.watch() also yields message (a whole message: its role, text, files and via or trigger; a reply, its toolCalls and reasoning; a note, its data) and status (the conversation's new status). operationId names the turn an event belongs to (null for a message no turn sent, like a person's reply). history() reads messages in the same shape. The type call is reserved for a phone call's moments.

Attributes
type| "text" | "reasoning" | "tool_call" | "tool_result" | "file" | "approval" | "operation" | "done" | "message" | "status" | (string & {})
textstring | null
toolstring | null
argumentsJsonObject | null
resultunknown
isErrorboolean
replyAgentReply | null
role"user" | "assistant" | "person" | "note" | null

A message's sender: user, assistant, person (someone it was handed off to) or note (agent.note).

heldJsonObject | null

A held tool_call: who approver is and, when the request is addressed to the scope you read as, the approval's request_id and page url.

status"active" | "awaiting_human" | "handed_off" | "compacting" | "compacted" | null

A status event's: the conversation's new status, or a turn's own (compacting, then compacted).

operationIdstring | null
rawJsonObject

The response JSON exactly as the API sent it.

fileAttachment | null

A file event's file.

filesAttachment[]

A message event's files.

toolCallsJsonObject[]

A message event's tool calls (a reply's): each {tool, arguments, result, is_error}, as its turn's events showed it.

approvalJsonObject | null

An approval event's: its id, summary, exact price (a purchase), expires_at and, read as the account, the url of the page where its owner approves.

operationJsonObject | null

An operation event's: the long action's id (an Operation's), kind, status and summary and, once the work reported some, its progress (Operation.progress, with its last 3 lines).

viaMessageVia | null

A user message's way in, when not the API.

dataJsonObject | null

A note message's data.

triggerMessageTrigger | null

A user message no person sent: what started its turn (Message.trigger).

reasoningReasoningLine[]

A message event's reasoning (a reply's): Message.reasoning.

Rehearsal

interface Rehearsal

A test run: a real turn of the agent (its model, instructions and tools) where a simulated world answers every tool call, so nothing is sent and no account is touched. toolCalls are the calls it made, each with the tool (its tool name, like gmail__search_emails), its arguments and the result the world answered (null if the world couldn't); transcript is the turn step by step: role assistant steps (its text between calls, then the reply) and tool steps. On a coding harness its own shell and file steps are tool steps with source harness: they ran for real, in the run's own sandbox. costUsd is what the run cost you.

Attributes
replystring
toolCallsJsonObject[]
transcriptJsonObject[]
scenariostring | null
costUsdnumber | null
operationIdstring | null
rawJsonObject

The response JSON exactly as the API sent it.

Wakeup

class Wakeup

One time an agent will be (or was) woken in a conversation. At its moment the conversation takes a turn whose message is the note, followed by what woke it: the time, the operation's outcome, a job's update, or a NoClick event. A running turn in that conversation goes first (one turn per conversation), and the wake-up waits behind it. Durable, delivered once, and billed and capped like any turn; a turn the account can't pay for fails it (status: "failed", error).

Attributes
idstring
agentIdstring
userIdstring | null

Whose conversation it wakes (None: the account's).

conversationstring

The conversation it wakes.

notestring

What the turn is told.

atDate | null

When it's due (a time wake-up), or when it became due.

whenJsonObject | null

What it waits on: { operation_id } or { event, filters } (null for a time wake-up).

everyCron | null

Its schedule, for a recurring wake-up (null for one that comes once); at is its next time.

firednumber

How many turns it has started (a recurring one counts up).

sourceWakeupSource

What set it: code (agent.wake), wake_me (the agent's own tool), update (a job's update for this agent as its parent), answer (the link it asked its user to connect an account with is done: connected or expired) or approval (a held call was decided).

statusWakeupStatus

pending, delivered (its turn started), canceled or failed; a recurring one stays pending until it's canceled.

wokenByJsonObject | null

What woke it: { at } for a time (once delivered), { operation_id, kind, status, result | error } once its operation settled, { update } for a job's update, and { event } (the event as Event.list reads it) for an event; null until then.

operationIdstring | null

The turn it started (an agent.message operation), once delivered.

depthnumber

How many wake_me wake-ups in a row led to it (0 for anything else).

errorJsonObject | null

Why it failed: { type, message }.

missedJsonObject | null

A recurring one's last missed time: { at, reason }, reason being credits, spend_cap (the account's monthly cap) or budget (the agent's, its key's or its user's); null if it never missed.

createdAtDate | null
deliveredAtDate | null

When its turn started (None until then).

operationOperation<AgentReply> | null

The turn it started, as an operation to wait on (null until delivered).

cancel

cancel(): Promise<this>

Cancel it while it's pending (Conflict once it was delivered, canceled or failed).

Returns

This wake-up, canceled.

update

update(
  options: { note?: string } & Pick<WakeTiming, "at" | "afterS" | "every">,
): Promise<this>

Change it while it's pending: its note, and its time with one of at, afterS and every (a one-off time makes a recurring one come once more). A delivery under way of what it said before starts no turn. One waiting on an operation or an event keeps that; Conflict once it was delivered, canceled or failed.

Parameters
options.notestring
options.atDate | string

A moment: a Date, or an ISO 8601 string with its offset.

options.everyCron

A routine: it wakes the conversation at each time of this Cron until it's canceled (tz: "user" follows the conversation's user). The note is what it's told, so the Cron takes no message.

options.afterSnumber

This many seconds from now.

Returns

This wake-up, as it is now.

Job

class Job extends Operation

Work one agent gave another: a spawned child's task (kind agent.task), or a message a coordinator sent with its agents tools (kind agent.message), whose only update is done. It's an Operation: wait() returns the AgentReply.

A task runs while the child works on it, across as many turns as it takes, and finishes when its conversation goes quiet with nothing left to continue it: no turn running, no wake-up pending, nothing waiting on a person. While it runs, step is working (a turn is running) or waiting (only a wake-up is pending); it's awaiting_human (step blocked) while it waits on a person: a held call, or a connection it asked its user for. It succeeded once the child stopped, its last reply the result (a child that needs a decision says so and stops; the parent's message to it starts a new job in the same conversation), failed when a turn failed, canceled when canceled (its running turn stops and its pending wake-ups are called off), and expired when the child's ttl_s ran out first.

Attributes
startedBystring | null

The agent whose job it is: a task's parent, whether your code spawned it or the parent did.

conversationstring | null

The working agent's conversation it runs in.

parentConversationstring | null

The parent's conversation its updates wake (null: they wake nobody and wait here).

requiredUpdates(string | JsonObject)[]

The updates its parent required, as on the wire: "done", "blocked", { before }, { every_s }.

latestUpdateJobUpdate | null

Its newest update, or null.

agentAgent | null

The agent doing the work (a lazy reference), or null.

liststatic

static list(options?: KindScopedFilters & { limit?: number }): Promise<Job[]>

Spawned tasks (kind agent.task), newest first; takes Operation.list's filters except kind. agent.jobs() reads an agent's message jobs too.

Parameters
options.limitnumber

Return at most this many.

options.clientNoClick
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

options.statusOperationStatus | "live" | readonly (OperationStatus | "live")[]

Statuses, or "live" for every non-terminal one.

options.agentstring | ApiObject

An Agent or agent id.

options.statusNotOperationStatus | readonly OperationStatus[]
options.keystring

The requesting key: its id or its prefix (nk_live_ab12).

options.createdAfterDate | string
options.createdBeforeDate | string
options.updatedAfterDate | string

Rows changed since (for polling).

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

Returns

Every matching job (or the first limit), each with its status, step and latest_update.

listPagestatic

static listPage(options?: KindScopedFilters & PageOptions): Promise<Page<Job>>

One page of jobs; pass nextCursor back as cursor.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.clientNoClick
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

options.statusOperationStatus | "live" | readonly (OperationStatus | "live")[]

Statuses, or "live" for every non-terminal one.

options.agentstring | ApiObject

An Agent or agent id.

options.statusNotOperationStatus | readonly OperationStatus[]
options.keystring

The requesting key: its id or its prefix (nk_live_ab12).

options.createdAfterDate | string
options.createdBeforeDate | string
options.updatedAfterDate | string

Rows changed since (for polling).

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

Returns

A page whose data holds the jobs and whose next_cursor is None on the last page.

summarystatic

static summary(options?: KindScopedFilters): Promise<OperationSummary>

How many jobs match, by status; takes Operation.summary's filters except kind.

Parameters
options.clientNoClick
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

options.statusOperationStatus | "live" | readonly (OperationStatus | "live")[]

Statuses, or "live" for every non-terminal one.

options.agentstring | ApiObject

An Agent or agent id.

options.statusNotOperationStatus | readonly OperationStatus[]
options.keystring

The requesting key: its id or its prefix (nk_live_ab12).

options.createdAfterDate | string
options.createdBeforeDate | string
options.updatedAfterDate | string

Rows changed since (for polling).

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

Returns

The number that match in total, and per operation status in by_status.

updates

updates(): Promise<JobUpdate[]>

Every update it sent its parent, oldest first.

Returns

Each JobUpdate with its kind, the child's text and, by kind, the call it was about to make, what it waits on, or the result.

jobFromIdstaticTypeScript only

static jobFromId(operationId: string, options?: CallOptions): Job

A lazy reference to a job by operation id: pick it up anywhere (Operation.fromId gives a plain operation).

Parameters
operationIdstringrequired
options.clientNoClick
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

JobUpdate

interface JobUpdate

One update a job sent its parent. text is what the child wrote: its last reply (done), what it wrote with the call, its reason (before; null on a coding harness, whose words NoClick sees only when its turn ends), what it wrote when asked (every), its message (message), or NoClick's line saying what it waits on (blocked). tool and arguments are the call a before update announces; result and error end a done one; waitingOn says what a blocked one waits on ({ kind: "connection" | "approval", url, operation_id }: a connect link it asked its user to open, with its url, or a held call, never with one, so no agent approves its child's call; person and sign_in are in invite-only beta); wakeupId is the parent's wake-up it set (null when nothing was to be woken).

Attributes
idstring
jobIdstring
agentIdstring | null
kindJobUpdateKind
textstring | null
toolstring | null
argumentsJsonObject | null
statusstring | null

The job's status then.

resultunknown
errorJsonObject | null
waitingOnJsonObject | null

A blocked update's wait: {kind, url, operation_id}, kind being connection (a link it asked its user to connect an account with: url) or approval (a held call; never a url, so no agent approves its child's call). person and sign_in are in invite-only beta.

wakeupIdstring | null
createdAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

Before

class Before

An update before a matching tool call runs: the call and what the child wrote with it, its reason. Patterns are written as policy writes them ("gmail.send_email_message", "stripe.*", "code"). The call runs right after (a call that must wait for someone is a policy requireApproval rule), and a coding harness's own shell commands and file edits aren't tool calls NoClick sees, so it can't match them (its words arrive only when its turn ends, so its update carries no reason).

Attributes
toolsstring[]

The tool patterns it covers.

toolsstring[]

Every

class Every

An update at least every intervalS seconds (60 or more) while the job works: NoClick asks the child for one once that long has passed since its last (on a coding harness by steering its running turn, on sdk before its next model call), and the tell_parent it answers with is the every update. A child that's only waiting isn't asked.

Attributes
intervalSnumber

How often, at most, the parent hears while the child works.

intervalSnumber

Agents

class Agents

The agents capability for an agent's tools: new Agents() (the same as "agents") gives it spawn, message, ask, status, list and cancel within its own scope, in its own conversations (in a channel, agents work by mentions), and Agents.only(...) some of them. spawn makes its own children (their updates wake it in the conversation it spawned from); message reaches the agents it can reach (a user's agent that user's and the account's, an account agent the account's), waiting up to 50 seconds for the reply, and a reply that takes longer, or one it doesn't wait for, is a job whose done update wakes it; ask asks one without stopping it; status reads an agent or a job; list takes Agent.list's filters; cancel stops a job it started. Its children get the capability only when it lists it for them. Policy names them agents.spawn ... agents.cancel; the model sees agents__spawn, ...

Attributes
toolsAgentsTool[]

The capability's tools this gives.

toolsAgentsTool[]

onlystatic

static only(...tools: AgentsTool[]): Agents

Some of the capability's tools: Agents.only("spawn", "status").

Parameters
toolsAgentsTool[]required
Returns

The capability narrowed to those tools, for tools= (on the wire, "agents.spawn", ...).

Platform

class Platform

NoClick itself for an agent's tools: new Platform() (the same as "noclick") gives it what a connected app gets on NoClick's MCP server, search and fetch (NoClick's guides and your account's objects), api_describe and api_call (any API operation), and quote, buy and delete, acting as the turn's key and the user it acts for, never more than that key may. The same gate judges them as any connected app: a purchase or a deletion waits for the account's owner, who approves it on NoClick with its exact price or what goes with it (the turn waits on them, and the call's outcome is the conversation's next turn); a secret's value never comes from the conversation; and a turn answering someone outside the agent's scope asks a person before acting outside the account. A long action it starts is an operation, which wake_me waits on, and watchers see approval and operation events. Platform.only(...) narrows it by capability group (without spend it has no quote or buy, without delete no delete) and by API area (a key's scopes: "domains", "phone", "agents"...), each narrowing only its own kind. Policy names its tools noclick.search ... noclick.delete.

Attributes
namesstring[]

What it's narrowed to: capability groups and API areas (empty: all of NoClick).

namesstring[]

What it's narrowed to: capability groups and API areas (empty: all of NoClick).

onlystatic

static only(...names: (PlatformGroup | (string & {}))[]): Platform

Part of NoClick: Platform.only("domains"), Platform.only("read"). Names are checked when the agent is saved.

Parameters
names(PlatformGroup | (string & {}))[]required
Returns

NoClick narrowed to those names, for tools= (on the wire, "noclick.read", ...).

Attachment

interface Attachment

A file on a message, kept as an account file at url. kind is image, audio, video or file; a voice clip has its durationMs and its waveform's peaks (loudness 0-1). Audio is kept as transcription reads it (a browser's WebM recording as MP3). A file an agent's conversation shows (in history, or a file event) has its name, url and mimeType, and no id: it was sent. The account's files (attachments()) have their id, to send again.

Attributes
namestring
urlstring
mimeTypestring
idstring | null
sizeBytesnumber | null
kind"image" | "audio" | "video" | "file"
voiceboolean
durationMsnumber | null
peaksnumber[] | null
rawJsonObject

The response JSON exactly as the API sent it.

attachments

function attachments(options?: AttachmentsOptions): Promise<Attachment[]>

The account's files, newest first: what its messages carried, the images and videos it made, its calls' recordings. A message to an agent sends any of them again in its files. The account's alone: read as a user, it's refused.

const [report] = await attachments({ query: "q3" });
await analyst.message("What changed since this?", { files: [report] });
Parameters
options.querystring

Keeps the files whose names contain it (any case).

options.limitnumber

How many, 1 to 100 (30 by default).

options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Each file as an Attachment with its id, name, url, mime_type and kind.