Agent
Agents: hosted agents you message by name.
class AgentA 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.
- Like every live object, it also has hydrate(), refresh() and raw.
| id | string | |
| origin | AgentOrigin | null |
|
| name | string | |
| model | string | null | The model it runs, as its harness names it ( |
| harness | HarnessName | null | What runs it: |
| modelConnection | string | null | The connection whose key or plan it thinks with, by name (null on |
| instructions | string | null | |
| tools | (string | JsonObject)[] | What it can use, as listed: refs, |
| canRequest | string[] | What it may ask its user to connect at run time. |
| userId | string | null | |
| workflowId | string | null | |
| nodeId | string | null | An app agent's step in its workflow (null for an API agent). |
| workflowName | string | null | An app agent's workflow, by name. |
| access | string | null | An app agent's workflow as you hold it: |
| enabled | boolean | null | Whether an app agent is switched on; a disabled one takes no messages. |
| appUrl | string | null | Where an app agent is changed: its workflow in the NoClick app. |
| parentId | string | null | The agent an ephemeral agent's budget is carved from. |
| ttlS | number | null | The time to live it was created with, in seconds (null if it isn't temporary); |
| expiresAt | Date | null | When a temporary agent expires (null if it isn't): it then stays readable, |
| budgetUsdPerMonth | number | null | |
| region | RegionName | null | The region its sandboxes run in, fixed when it was created; |
| machineId | string | null | Invite-only beta. The |
| createdAt | Date | null | |
| browserProfileId | string | null | Invite-only beta. The browser profile its |
| cardId | string | null | Invite-only beta. The card it holds and pays with (null: none of its own). |
| volumes | Record<string, string> | The volumes its shell mounts: |
| memoryId | string | null | Its own memory ( |
| memories | { id: string; writes: boolean }[] | null | The memories it reads besides its own, in order: each |
| secretIds | string[] | The secrets in its shell's environment, in order (a later one's key wins). |
| timezone | string | null | The IANA timezone its turns tell the time in (null: the acting user's, else UTC). |
| repos | JsonObject[] | The repositories cloned into its workspace: each its |
| network | NetworkAccess | null | What its shell and code reach: |
| shell | boolean | null | Whether it has a shell (the |
| status | AgentStatus | null |
|
| lastActiveAt | Date | null | When a turn of its last started or ended (null: it never ran, or hidden like |
| runningTurns | number | null | How many of its turns are queued, running or waiting on a person, any conversation (null: hidden like |
| childCount | number | null | How many live (not expired) children it has ( |
| jobId | string | null | The task it was spawned with (its operation id), or null. |
| usedBy | UsedBy[] | The apps that bind it: |
| paused | boolean | Whether |
| job | Job | null | The task it was spawned with, as a |
| triggerKinds | string[] | The kinds of its triggers ( |
| consoleUrl | string | null | This agent in the developer console (null off the hosted API). |
| a2aUrl | string | The A2A JSON-RPC endpoint ( |
| memory | AgentMemory | What it remembers across conversations: |
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).
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.
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.
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).
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.
In fromName, null clears it, as browserProfile and card do.
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.
What wakes it without a message: OnWebhook, OnEvent, OnPlatformEvent, Cron and OnQueue.
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.*.
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.
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.
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.
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.
Repositories cloned into its workspace (/workspace/) 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.
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.
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.
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.
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.
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.
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The parent agent an ephemeral agent's budget is carved from.
The new agent, loaded.
fromNamestatic
static fromName(
name: string,
options?: AgentCreateOptions & { createIfMissing?: boolean },
): AgentA 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.
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.
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.
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).
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.
In fromName, null clears it, as browserProfile and card do.
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.
What wakes it without a message: OnWebhook, OnEvent, OnPlatformEvent, Cron and OnQueue.
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.*.
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.
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.
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.
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.
Repositories cloned into its workspace (/workspace/) 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.
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.
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.
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.
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.
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.
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The parent agent an ephemeral agent's budget is carved from.
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): AgentA lazy reference to an agent by NoClick id.
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.
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);Only agents with this status.
Only agents with a turn since then.
Only the children of this agent (an Agent or id).
true: only agents with a ttlS; false: only agents without one.
Only agents on this harness.
created (the default: newest first) or last_active (most recently active first, those that never ran last).
Only agents made through the API (api) or built in the NoClick app (app).
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
Only agents with this status.
Only agents with a turn since then.
Only the children of this agent (an Agent or id).
true: only agents with a ttlS; false: only agents without one.
Only agents on this harness.
created (the default: newest first) or last_active (most recently active first, those that never ran last).
Only agents made through the API (api) or built in the NoClick app (app).
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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" });The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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");The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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.
The file's name (a File has its own).
Its type (a Blob has its own; else read from the name).
A recorded voice clip (audio).
A voice clip's waveform: loudness 0-1, at most 64 numbers.
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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" });Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
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.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
When NoClick makes the child report, beside "done" (always on): "blocked", new Before(...), new Every(...).
The parent's conversation its updates wake; without one they wake nobody and wait on the job.
The child's standing instructions: what its updates should say, and when to reach out freely.
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.
Its budget, carved from its parent's.
It expires this many seconds after it's made.
The parent's model when omitted.
The parent's harness when omitted.
The parent's model connection when omitted.
<parent>-<8 hex> when omitted.
Whose conversation conversation is (an account parent talking to a user: that user's thread).
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.
Return at most this many.
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).
Statuses, or "live" for every non-terminal one.
task (spawned), or message (sent with its agents tools).
The agent doing the work (an Agent or id).
The parent's conversation that started them.
Return at most this many.
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
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.
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.
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.
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.
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." });What the turn is told, 1 to 4,000 characters.
A moment: a Date, or an ISO 8601 string with its offset.
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.
With an event when: dotted paths into the event's data that must equal these values.
Whose conversation it is, as message() takes it.
This many seconds from now.
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.
Return at most this many.
undefined = the ambient user (asUser), null = the account itself.
Which users the read covers (user_id query), instead of acting as one (user).
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.
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.
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.
inboxes
inboxes(): Promise<Inbox[]>The inboxes whose mail wakes it (created or updated with it as their agent).
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.
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.
This agent, with paused false.
workspace
workspace(conversation: string, options?: { user?: UserOption }): AgentWorkspaceThe files it works on in one conversation. Sends nothing yet.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The conversation's workspace, whose files, read, write and url reach its files.
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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 AgentGrantA 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.
| id | string | |
| connection | string | |
| integration | string | |
| operations | string[] | null | |
| status | "requested" | "active" | |
| reason | string | null | |
| conversation | string | null | |
| createdAt | Date | null | |
| grantedAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
AgentReply
interface AgentReplyThe agent's answer to one message.
| text | string | |
| conversation | string | null | Pass back as |
| toolCalls | JsonObject[] | The turn's tool calls, each |
| operationId | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
| modelUsage | ModelUsage | null | The turn's model calls on your own key or plan (null on NoClick's key, whose cost is its |
Conversation
interface ConversationOne thread with an agent (a user's, or the account's own).
| conversation | string | Pass as |
| userId | string | null | |
| title | string | null | |
| preview | string | null | |
| turns | number | null | |
| costUsd | number | null | |
| lastActivity | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
| status | ConversationStatus | null |
|
| handedOffTo | string | null | Who a |
| modelUsage | ModelUsage | null | Its model calls on your own key or plan, all turns together (null on NoClick's key). |
Message
interface MessageOne 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).
| role | string | |
| text | string | |
| createdAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
| files | Attachment[] | The files it carried (a |
| toolCalls | JsonObject[] | A reply's tool calls: each |
| via | MessageVia | null | How a |
| data | JsonObject | null | A |
| trigger | MessageTrigger | null | What started the turn of a |
| reasoning | ReasoningLine[] | A reply's reasoning, as its turn's |
HarnessInfo
interface HarnessInfoWhat 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.
| name | HarnessName | What |
| label | string | null | |
| version | string | null | The version NoClick runs (null for |
| defaultModel | string | The model an agent on it gets when you give none. |
| customModels | boolean | Whether |
| modelConnection | "required" | "optional" |
|
| integrations | string[] | The model providers ( |
| streaming | "tokens" | "final" |
|
| shell | "built_in" | "code_capability" |
|
| notes | string[] | What to know before choosing it (a model that needs a particular key, say). |
| raw | JsonObject | 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 });Return at most this many.
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 HarnessModelA model a harness offers, by the id its model takes.
| id | string | |
| label | string | null |
ModelUsage
interface ModelUsageWhat 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.
| inputTokens | number | |
| outputTokens | number | |
| cachedTokens | number | |
| usd | number | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
AgentMemory
class AgentMemoryagent.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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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).
Return at most this many.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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).
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
entries
entries(options?: { user?: UserOption }): Promise<MemoryEntry[]>list, as Memory calls it.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
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.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
MemoryEntry
interface MemoryEntryOne 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.
| name | string | |
| description | string | |
| content | string | null | |
| version | number | |
| updatedAt | Date | null | |
| updatedBy | "agent" | "api" | "console" | null | |
| userId | string | null | |
| conversation | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
AgentWorkspace
class AgentWorkspaceThe 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.)
| conversation | string | 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).
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.
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.
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).
The link; it works for expires_in_s seconds (an hour by default, a day at most).
WorkspaceFile
interface WorkspaceFileA file in a conversation's workspace; url downloads it without a key for about an hour.
| path | string | Relative to |
| sizeBytes | number | |
| modifiedAt | Date | null | |
| url | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
AgentEvent
interface AgentEventOne 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.
| type | | "text" | "reasoning" | "tool_call" | "tool_result" | "file" | "approval" | "operation" | "done" | "message" | "status" | (string & {}) | |
| text | string | null | |
| tool | string | null | |
| arguments | JsonObject | null | |
| result | unknown | |
| isError | boolean | |
| reply | AgentReply | null | |
| role | "user" | "assistant" | "person" | "note" | null | A |
| held | JsonObject | null | A held |
| status | "active" | "awaiting_human" | "handed_off" | "compacting" | "compacted" | null | A |
| operationId | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
| file | Attachment | null | A |
| files | Attachment[] | A |
| toolCalls | JsonObject[] | A |
| approval | JsonObject | null | An |
| operation | JsonObject | null | An |
| via | MessageVia | null | A |
| data | JsonObject | null | A |
| trigger | MessageTrigger | null | A |
| reasoning | ReasoningLine[] | A |
Rehearsal
interface RehearsalA 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.
| reply | string | |
| toolCalls | JsonObject[] | |
| transcript | JsonObject[] | |
| scenario | string | null | |
| costUsd | number | null | |
| operationId | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
Wakeup
class WakeupOne 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).
- Like every live object, it also has hydrate(), refresh() and raw.
| id | string | |
| agentId | string | |
| userId | string | null | Whose conversation it wakes ( |
| conversation | string | The conversation it wakes. |
| note | string | What the turn is told. |
| at | Date | null | When it's due (a time wake-up), or when it became due. |
| when | JsonObject | null | What it waits on: |
| every | Cron | null | Its schedule, for a recurring wake-up (null for one that comes once); |
| fired | number | How many turns it has started (a recurring one counts up). |
| source | WakeupSource | What set it: |
| status | WakeupStatus |
|
| wokenBy | JsonObject | null | What woke it: |
| operationId | string | null | The turn it started (an |
| depth | number | How many |
| error | JsonObject | null | Why it failed: |
| missed | JsonObject | null | A recurring one's last missed time: |
| createdAt | Date | null | |
| deliveredAt | Date | null | When its turn started ( |
| operation | Operation<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).
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.
A moment: a Date, or an ISO 8601 string with its offset.
This many seconds from now.
This wake-up, as it is now.
Job
class Job extends OperationWork 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.
- Inherits from Operation.
| startedBy | string | null | The agent whose job it is: a task's parent, whether your code spawned it or the parent did. |
| conversation | string | null | The working agent's conversation it runs in. |
| parentConversation | string | 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: |
| latestUpdate | JobUpdate | null | Its newest update, or null. |
| agent | Agent | 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.
Return at most this many.
undefined = the ambient user (asUser), null = the account itself.
Statuses, or "live" for every non-terminal one.
An Agent or agent id.
The requesting key: its id or its prefix (nk_live_ab12).
Rows changed since (for polling).
Which users the read covers (user_id query), instead of acting as one (user).
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.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
undefined = the ambient user (asUser), null = the account itself.
Statuses, or "live" for every non-terminal one.
An Agent or agent id.
The requesting key: its id or its prefix (nk_live_ab12).
Rows changed since (for polling).
Which users the read covers (user_id query), instead of acting as one (user).
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.
undefined = the ambient user (asUser), null = the account itself.
Statuses, or "live" for every non-terminal one.
An Agent or agent id.
The requesting key: its id or its prefix (nk_live_ab12).
Rows changed since (for polling).
Which users the read covers (user_id query), instead of acting as one (user).
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.
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): JobA lazy reference to a job by operation id: pick it up anywhere (Operation.fromId gives a plain operation).
JobUpdate
interface JobUpdateOne 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).
| id | string | |
| jobId | string | |
| agentId | string | null | |
| kind | JobUpdateKind | |
| text | string | null | |
| tool | string | null | |
| arguments | JsonObject | null | |
| status | string | null | The job's status then. |
| result | unknown | |
| error | JsonObject | null | |
| waitingOn | JsonObject | null | A |
| wakeupId | string | null | |
| createdAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
Before
class BeforeAn 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).
| tools | string[] | The tool patterns it covers. |
| tools | string[] |
Every
class EveryAn 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.
| intervalS | number | How often, at most, the parent hears while the child works. |
| intervalS | number |
Agents
class AgentsThe 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, ...
| tools | AgentsTool[] | The capability's tools this gives. |
| tools | AgentsTool[] |
onlystatic
static only(...tools: AgentsTool[]): AgentsSome of the capability's tools: Agents.only("spawn", "status").
The capability narrowed to those tools, for tools= (on the wire, "agents.spawn", ...).
Platform
class PlatformNoClick 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.
| names | string[] | What it's narrowed to: capability groups and API areas (empty: all of NoClick). |
| names | string[] | What it's narrowed to: capability groups and API areas (empty: all of NoClick). |
onlystatic
static only(...names: (PlatformGroup | (string & {}))[]): PlatformPart of NoClick: Platform.only("domains"), Platform.only("read"). Names are checked when the agent is saved.
NoClick narrowed to those names, for tools= (on the wire, "noclick.read", ...).
Attachment
interface AttachmentA 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.
| name | string | |
| url | string | |
| mimeType | string | |
| id | string | null | |
| sizeBytes | number | null | |
| kind | "image" | "audio" | "video" | "file" | |
| voice | boolean | |
| durationMs | number | null | |
| peaks | number[] | null | |
| raw | JsonObject | 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] });Keeps the files whose names contain it (any case).
How many, 1 to 100 (30 by default).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
Each file as an Attachment with its id, name, url, mime_type and kind.