ChannelAdapter
What a channel adapter (slack(), whatsapp(), github()) returns.
verify, parse, ack and render are pure.
Properties
agentstringrequiredThe host agent key this channel routes to.
capabilitiesChannelCapabilitiesrequiredWhat 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>requiredProvider limits (message bytes, rate).
secretsRecord<string, Secret>requiredThe 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>rawRawRequestrequiredThe 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[]>rawRawRequestrequiredThe 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): RawResponserawRawRequestrequiredThe 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>requiredThe 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[]eventEventrequiredA 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.
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>opJsonObjectrequiredOne 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_keystringrequiredThe 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>requiredThe 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_keystringrequiredThe effect key perform was given for the send being reconciled.
opJsonObjectrequiredThe op perform was given for this key, read back from its recorded tool_call, so the lookup can search the right conversation.