Human
Humans: ask a person, get an approval, send a notice, request a connection.
class HumanA person to reach. user.human (or new Human(), meaning the user
current at each call, or the one a session or user-pinned key acts for)
is the user; Human.owner() is your account's owner; new Human({ email }) is anyone else.
Every method returns an operation: await req.wait() for the outcome.
via says where a message goes: "auto" (the default), or a list of "web" (only the page: you
pass request.url on), "email", and for the owner "whatsapp" and "imessage", sent from
NoClick's own numbers to the number they text NoClick from. "auto" is the app the owner last
texted NoClick on, else email. "sms" and "call" throw NotAvailable for now. What couldn't be
sent is listed in undelivered, never implied.
ownerstatic
static owner(options?: { client?: NoClick }): HumanYour account's owner: the person behind the account, reached by email and on the app they text
NoClick from. Only your account reaches them: it always acts as your account, inside asUser too,
and a user's session or a key pinned to a user throws PermissionDenied.
await Human.owner().notify("The site is live: https://morrowbakery.com");The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The owner, to message, ask, put in an agent's tools= or answer_with.
answerWith
answerWith(
agent: Agent | string | null,
options?: { conversation?: string },
): Promise<this>Send what this person texts or says to NoClick's own numbers (its WhatsApp and iMessage numbers and
its voice number) to agent (one of your account's). A text's reply goes back on the app they texted
on once the agent's turn ends, and texts sent while it's busy go in its next turn, in order; on a call,
each thing they say is a turn whose reply is read aloud as it's written. null hands them back to
NoClick's assistant. Only Human.owner() reaches NoClick's numbers: your users reach an agent on a
number of your own (PhoneNumber.answerWith). conversation is the agent's conversation each text or
call lands in, a template over {channel} (whatsapp, imessage or call); omitted, "owner".
Give an inbox and a number the same key and the person's email, calls and texts are one conversation.
const assistant = Agent.fromName("assistant");
await Human.owner().answerWith(assistant);
await assistant.message("What's on today?", { conversation: "owner" }); // the same threadThis person.
answering
answering(): Promise<Agent | null>The agent this person's texts to NoClick's own numbers go to (answerWith), or null when NoClick's assistant answers them.
The noclick.Agent, or None.
addEmail
addEmail(email: string): Promise<void>Send a code to email for the owner of an account made by texting NoClick (which has none);
confirmEmail with the code makes it theirs. Throws Conflict when the account already has an
email, RateLimited after too many codes.
const owner = Human.owner();
await owner.addEmail("maya@morrowbakery.com");
await owner.confirmEmail(code);confirmEmail
confirmEmail(code: string): Promise<OwnerEmail>The code addEmail sent: on a match the email is the owner's to sign in with, or, when an account
already has it, that account takes this one in (merged). Whether an account has the email is said
only once the code matches. status is added, or verified when an agent's turn confirmed it
(it's added once that turn ends).
const confirmed = await Human.owner().confirmEmail("482913");The confirmed email.
only
only(...tools: HumanTool[]): HumanOperationsSome of the tools this person gives an agent, for tools. In an
agent's tools a Human gives it three, each addressed only to this person: notify, ask
(the turn waits, awaiting_human, and the answer arrives as the next turn) and hand_off
(the conversation goes to this person, with a page and an email carrying the transcript and a
reply box; their replies post as person messages and the agent stays quiet until
agent.handBack(conversation); on a call it's transferred to the person's phone). Policy
names them human.notify, human.ask and human.hand_off.
const manager = new Human({ email: "ops@acme.com" });
await Agent.create("support", { instructions: "...", tools: ["search", manager.only("notify", "ask")] });A ref to just those tools of this person, to list in tools=.
ask
ask(
message: string,
options?: { options?: string[]; via?: Via; expiresInS?: number },
): Promise<HumanRequest<Answer>>Ask a question; wait() resolves to an Answer.
The request, already sent. wait() blocks until the person answers
and gives what they picked (choice) and wrote (text).
approve
approve(
message: string,
options?: { details?: unknown; via?: Via; expiresInS?: number },
): Promise<HumanRequest<boolean>>Ask for a yes/no; wait() resolves to true when approved.
The request, already sent. wait() gives True if they approve
and False if they decline.
notify
notify(message: string, options?: { via?: Via }): Promise<HumanRequest<null>>Send a notice (the operation succeeds once it's sent).
The request, already sent and its operation already succeeded, so
wait() returns None at once. undelivered names any channel that failed.
connect
connect(
connection: string | Connection,
options?: { reason?: string; redirectUrl?: string },
): Promise<ConnectLink>Ask this person to connect connection (a Connection or its name, in
this person's user); wait() resolves to the connected Connection.
The link, already emailed: its url and when it expires_at.
wait() gives the connected Connection.
HumanRequest
class HumanRequest extends OperationA request to a person; also the operation that finishes when they answer.
- Inherits from Operation.
| requestId | string | null | The request's own id (the operation's is |
| requestStatus | HumanRequestStatus | null |
|
| request | JsonObject | The request as created: |
| url | string | null | The page where the person answers ( |
| deliveredVia | string[] | |
| undelivered | JsonObject[] | Channels that failed, each with a |
| note | string | null | What the approver wrote with their answer (null until answered, or if they wrote nothing). |
liststatic
static list(
options?: HumanRequestFilters & { limit?: number },
): Promise<HumanRequest<unknown>[]>Requests your code and agents sent, newest first (or the first limit).
"owner": only requests the signed-in account owner may answer; "code": only those your code
may answer with approve or decline, leaving out the ones answered only signed in to NoClick (a
held purchase or deletion, whose request.signed_in_only is true).
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 request, fetched page by page. Each is also the
operation you can wait() on; request_status is the request's own status.
listPagestatic
static listPage(
options?: HumanRequestFilters & PageOptions,
): Promise<Page<HumanRequest<unknown>>>One page of requests; pass nextCursor back as cursor.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
"owner": only requests the signed-in account owner may answer; "code": only those your code
may answer with approve or decline, leaving out the ones answered only signed in to NoClick (a
held purchase or deletion, whose request.signed_in_only is true).
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 requests and whose next_cursor is None on the last page.
summarystatic
static summary(options?: KindScopedFilters): Promise<OperationSummary>How many human-request operations (ask, approve, notify) match, by operation status.
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.
approve
approve(options?: { note?: string }): Promise<this>Approve it from your own code, as the person it waits on: with a key acting for your account,
an approval routed to your account; with a user's session or inside asUser, one addressed to
that user (anyone else gets PermissionDenied). A held operation call then runs exactly as it
was held (a held shell command or other tool, the agent makes again itself), and the agent gets
a turn in the same conversation with its result, its reply going out where the conversation
lives: on an email thread, the same thread (the inbox agent's reply tool is bound to the
thread's latest message).
This request, answered: request_status is answered and note is yours.
decline
decline(options?: { note?: string }): Promise<this>Decline it: a held call never runs, and the agent gets a turn saying so, with your note.
This request, answered: request_status is answered and note is yours.
HumanOperations
class HumanOperationsSome of a person's tools for an agent (human.only(...)), for tools.
| human | Human | |
| tools | HumanTool[] |
Answer
interface AnswerWhat the person chose (choice) and/or wrote (text).
| choice | string | null | |
| text | string | null | |
| raw | unknown | The response JSON exactly as the API sent it. |
OwnerEmail
interface OwnerEmailAn email confirmed for the owner (Human.confirmEmail).
| string | ||
| status | string |
|
| merged | boolean | An account that already had the email took this one in. |