Examples
Support bot
Add a typed support operation or persistent ticket thread to your product.
Use a function for one question. Use an agent when a support ticket needs many messages, tools, approvals, or child investigations. Your product keeps identity, ticket rules, and the customer UI.
Define the support function
import { flary, z } from "flary";
const app = flary({ model: "openai/gpt-5" });
const searchDocs = app.fn({
description: "Search product documentation",
input: z.object({ query: z.string().min(1) }),
output: z.array(
z.object({
title: z.string(),
url: z.string().url(),
}),
),
run: ({ query }) => docs.search(query),
});
const tools = app.tools({ searchDocs });
export const support = app.fn({
input: z.object({ question: z.string().min(1) }),
output: z.object({
answer: z.string(),
sources: z.array(z.string().url()),
}),
tools,
prompt: ({ question }) => `Answer with product facts and sources.\n\n${question}`,
});
Serve it from the generated Worker:
export default app.serve({ support });
Call it from your product
import { flary } from "flary/client";
import type { support } from "./support";
const api = flary<{ support: typeof support }>({
baseUrl: "https://support.example.com",
headers: () => ({ authorization: `Bearer ${sessionToken()}` }),
});
const result = await api.support({
question: "How do I change my plan?",
});
Your application owns login, customer identity, billing, and the screen. Flary owns model execution, tools, validation, and durable runs.
Keep one thread per ticket
export const supportAgent = app.agent({
name: "support",
instructions: "Resolve the support issue with approved product facts.",
tools,
});
Store the product ticket ID with thread.ref.threadId. Reopen that thread for each reply. See
Build your UI or bot for the transport pattern.