Skip to main content
Configure the model and createAgent options in src/agent.ts. The starter already connects the agent to its tools, test people and hosting environment.
These options apply to the messaging agent. An MCP server or CLI tool command does not need a model key; the host supplies its model or invokes a tool directly.

Models

openAICompatible works with OpenAI-compatible APIs. With no explicit apiKey or baseURL, it uses the first non-empty key in this order: With no key, it stops immediately and names the supported variables.
Use your local server’s address and model id in the second example. A server that needs a key can also receive apiKey explicitly. MODEL sets the default model id. The starter passes CAFE_MODEL when set. Otherwise each provider has a default in src/model.ts. Set contextTokens to tell Flow the model’s context-window size.

Use Flow’s model key

flow setup writes FLOW_KEY, which can use the account’s $2 of trial model credit. A provider key takes priority over it. flow status reports the remaining credit without printing the key. flowModel({ model }) explicitly selects Flow’s hosted models; its default is anthropic/claude-haiku-5.5. GET /models on the configured Flow model server lists the models it offers. Set FLOW_MODEL_URL to use another Flow model server.
flow setup --rotate key replaces FLOW_KEY. The old key works for another 24 hours; --now ends it immediately. Neither command prints the full key.Exhausted credit returns trial_credit_used with a next step. Add your own provider key to continue with that provider.

Transcribe a voice note

For a local audio file named voice.ogg:
Transcription
This uses the same Flow key and model-server address. It accepts a Blob, File, Buffer, Uint8Array or ArrayBuffer, up to 15 MB. language is optional and detected when omitted. Errors include a message, next step, code and HTTP status.

createAgent options

The tables below cover common options. The TypeScript AgentOptions definition is the complete contract.

Instructions and tools

Channels and identity

See messaging and people for identity and time-zone behavior, and reminders and nudges for delivery rules.

State and hosting

Self-hosting covers persistence and restart handling. See Deployment for Flow hosting and Traces for observability.

Turn timing and history

Durations are milliseconds. A tool’s own deadlineMs overrides the agent’s value for that tool.

Message hooks and templates

beforeSend(message, { channel, address, info, origin }) runs for messages, carousels and templates on every channel. Return nothing to send the input, another message to replace it, or { refuse: "why" } to tell the agent to try again.It runs before platform content checks. History, transcripts and test judges see what was actually sent.An edit’s new text runs through it too, as a message with only text, and context.edit.messageId names the message being edited. A replacement is what goes out; a refusal sends nothing.
On channels whose info has edits and unsends (Telegram and iMessage on Flow Messaging, or a custom UI with editMessage and unsendMessage), the agent is offered edit_message ({ message_id, text }) and unsend_message ({ message_id }). Its send results there name each message ({"delivered":true,"channel":"imessage","message_id":"msg_..."}). WhatsApp and SMS offer neither tool.The platform decides how late an edit or unsend may come. Flow Messaging refuses a late one when it is made (422 unsupported_content with edit_window_closed, unsend_window_closed, first_message_not_editable or not_on_sms), and the agent gets that refusal as its tool result, for example Not edited: unsupported_content (edit_window_closed, on imessage): iMessage allows edits within 15 minutes of sending; .... Nothing is sent instead.Your own code gets the id too: a send’s SendReceipt.messageId, the messageId on message.out events, and a sent nudge’s NudgeResult.messageId. message.edited and message.unsent events record each change. Requires @flow-engineer/flow 0.7.0 or later.
intercept(conversationId, text, message) sees the incoming channel and any STOP, START or HELP classification in message.keyword.Its answer is stored in history and the transcript. STOP and START are enforced even if the hook returns an answer or throws. See keyword handling.