Threads AI

ChannelAdapter

What a channel adapter (slack(), whatsapp(), github()) returns.

verify, parse, ack and render are pure.

A protocol: adapters implement it.

Properties

agentstringrequired

The host agent key this channel routes to.

capabilitiesChannelCapabilitiesrequired

What the provider can do for delivery. The host reads lookup and dedup_window_ms to decide how an uncertain send is settled; the other flags are declarative.

limitsRecord<string, number>required

Provider limits (message bytes, rate).

secretsRecord<string, Secret>required

The credentials perform needs, by name. The host resolves them at ready() (missing_secret) and passes their values as perform's credentials; they never reach a sandbox, the log or a prompt.

Methods

verify

Checks the provider's signature over the raw webhook bytes and returns who sent it. Return unverified for anything that doesn't check out: the host answers 401 and stores nothing.

verify(raw: RawRequest): Result<VerifiedDelivery>
rawRawRequestrequired

The webhook exactly as received: lowercased header names and the body's exact bytes, which the signature covers. See RawRequest.

Returns an error value with one of these codes: unverified.

parse

Turns a verified webhook into its batch of inbound items, in order. Return invalid for a body you can't read: the host answers 400 and stores nothing.

parse(raw: RawRequest): Result<readonly Inbound[]>
rawRawRequestrequired

The same webhook verify just accepted. See RawRequest.

Returns an error value with one of these codes: invalid.

ack

The synchronous reply to the provider (usually a 200, or the provider's URL challenge). The host sends it only after every item of the batch is stored.

ack(raw: RawRequest): RawResponse
rawRawRequestrequired

The webhook being answered. See RawRequest.

challenge

A provider's GET subscription check on the webhook URL (WhatsApp hub.mode/hub.verify_token/hub.challenge). Pure: compares the token with the adapter's secret in constant time. unverified answers 401 and nothing is stored.

challenge(query: Record<string, string>): Result<RawResponse>
queryRecord<string, string>required

The GET request's query parameters by name, for example hub.mode, hub.verify_token and hub.challenge.

Returns an error value with one of these codes: unverified.

render

Outbound ops (adapter-defined JSON).

render(event: Event): readonly JsonObject[]
eventEventrequired

A log event to reply with: a turn's final model_response or an open approval card. Return one op per message to send, or none.

renderText / render_text

Outbound ops for a plain message the host writes itself: an open ask_user question with its choices, or the correction after a reply that matched none of them.

renderText(text: string): readonly JsonObject[]
textstringrequired

The message text, never empty.

perform

Sends one op to the provider and says what is known about delivery. Answer definite_not_sent only when you can prove nothing reached the provider; any doubt is outcome_unknown, which the host reconciles instead of re-sending.

perform(op: JsonObject, effectKey: string, credentials: Record<string, string>): Promise<DeliveryOutcome>
opJsonObjectrequired

One op from render, with the conversation's address, installation_id and last_inbound_at added by the host. It is the channel_send tool call's recorded input.

effectKey / effect_keystringrequired

The send's effect key, <branch_id>:<call_id>. Embed it where the platform allows, so lookup and provider dedup can find this send again.

credentialsRecord<string, string>required

The values of the adapter's secrets, by the same names, resolved by the host on the host side.

lookup

found carries the platform_ref. op is the op perform was given for this key (from its recorded tool_call), since a platform lookup is scoped to its conversation.

lookup(effectKey: string, op: JsonObject): Promise<LookupResult<string>>
effectKey / effect_keystringrequired

The effect key perform was given for the send being reconciled.

opJsonObjectrequired

The op perform was given for this key, read back from its recorded tool_call, so the lookup can search the right conversation.

Edit on GitHub

On this page