Generated operations
The eleven generated document families, what each covers, how the names are formed, and what happens when you add an operation.
Codegen runs one entry per module, over that module's own operations.graphql, so identical
fragment names repeated across modules never collide in a single run.
The eleven families
| Family | Import | Read by | What it covers |
|---|---|---|---|
core | ~api/generated/core/graphql | The shell, and every module | Identity, the bot and workspace lists, the role-and-permission read, file readback, per-user storage, and the preview pair a test chat starts from. 11 operations. |
livechat | ~api/generated/livechat/graphql | livechat (Inbox) | The conversation list and one thread's messages, sends for each channel, read state, take-over, assignment, notes and WhatsApp templates. 46 operations, 5 of them subscriptions. |
contacts | ~api/generated/contacts/graphql | contacts | Contact lists and counts, the bot attributes catalog, per-contact attribute edits, assignment, stage, and CSV import and export as background tasks. 40 operations. |
deals | ~api/generated/deals/graphql | deals | A deal is a contact carrying a salesStageV2 value: board columns, totals, stage moves, field edits, the table view and its exports. 28 operations. |
knowledge-base | ~api/generated/knowledge-base/graphql | knowledge-base | The structured record under bot.fuelyConfig.knowledgeBase, FAQs, the goods catalog, specialists, and the read-only conversation scan the Gaps source runs. 23 operations, and no subscription — there is none in the schema to have. |
coworker | ~api/generated/coworker/graphql | coworker (Copilot) | The operator-facing assistant chat: conversations per user and bot, sends that return before the reply arrives, tool approvals, streaming stop. 16 operations. |
bookings | ~api/generated/bookings/graphql | bookings | Appointments over bookingsV2, availability, staff and their Google Calendar links, the services catalog, the booking config and the bot time zone. 37 operations. |
automations | ~api/generated/automations/graphql | automations (AI agent) | How the AI behaves, one automation per scope: the settings, their inherit-from-parent twins, the media and ad pickers, and the preview conversation. 49 operations. |
flow-builder | ~api/generated/flow-builder/graphql | flow-builder | Flows, groups, blocks, block elements, buttons and connections. 233 operations, 224 of them mutations, because every element type has its own add mutation. |
ads-optimization | ~api/generated/ads-optimization/graphql | ads-optimization | Event sets over the one automation scope that carries them, their ad lists and event lists, and the inheritance between a custom set and the base one. 14 operations. |
publishing | ~api/generated/publishing/graphql | publishing | Account state, the media library, four publish mutations and the connect URL. 11 operations. |
Counts are top-level definitions in each operations.graphql. Outside the app — a Node script, the
wizard — the same files are reachable as @chatfuel/api-client/generated/<family>.
A module may import its own family or core, and nothing else. Validate pass 10 fails the build on
a crossing import, which is what keeps one module's screen from quietly depending on another
module's schema knowledge.
How the names are formed
documentMode: 'string' means every document is a printed TypedDocumentString, not an AST. An
operation becomes <OperationName>Document and a fragment becomes <Name>FragmentDoc:
query InstagramAccountState is exported as InstagramAccountStateDocument, and
fragment InstagramAccountRef as InstagramAccountRefFragmentDoc.
The string mode was chosen for size. Every AST mode inlines each fragment's object literal into
every operation that spreads it, and flow-builder spreads ElementParts from 153 places — a
5.5 MB chunk no bundler can dedupe. A post-codegen pass then prints each fragment once per file and
interpolates the constant, so the operation text still carries its fragments, as text that gzips.
You never name the generated types in module code. Import the document, hand it to the client, and the result type comes with it:
import { InstagramAccountStateDocument } from '~api/generated/publishing/graphql'; useEffect(() => {
let live = true;
setGate({ state: 'loading' });
client
.query(InstagramAccountStateDocument, { botID: botId })
.then((data) => {
if (!live) return;
const scope = data.bot.contactScopes.find(
(candidate): candidate is Extract<typeof candidate, { instagramAccount: Account }> =>
'instagramAccount' in candidate && Boolean(candidate.instagramAccount),
);
const account = scope?.instagramAccount ?? null;
if (!account) setGate({ state: 'absent' });
else setGate(canPublish(account) ? { state: 'ready', account } : { state: 'unpermitted', account });
})
.catch((err: unknown) => {
if (!live) return;
setGate({ state: 'error', message: errorMessage(err) });
});
return () => {
live = false;
};
}, [client, botId, tick, refreshToken]);What the generator emits
Adding or changing an operation
Edit modules/<id>/skill/examples/operations.graphql — that file is the source document, not the
generated one — then run pnpm codegen at the repository root, which runs graphql-codegen and the
fragment hoist. pnpm validate is what checks the result.
| Gate | What it fails on |
|---|---|
| Pass 0, documents | An operation that does not validate against the bundled schema, with the line it is on. |
| Pass 3, name collisions | Two operations anywhere with the same name. Fragments may repeat across families only with byte-identical bodies — which is why bookings prefixes its specialist and service operations even though knowledge-base reaches the same entities. |
| Pass 9, codegen coverage | A module id in codegen.ts with no operations.graphql, or a ready module with an app and an operations.graphql that is missing from the list. A module with no Chatfuel operations at all — auth, which talks to Supabase — must stay out of the list. |
| Pass 10, import boundaries | A module importing a generated family that is neither its own nor core. |
The same operations.graphql is copied into a scaffolded app as part of the module's agent skill,
so the coding agent working in that app reads the validated operations rather than guessing at the
schema. What runs them is the client the module receives.
What a module receives
The ModuleClient a module root is handed by props, the options createChatfuelClient takes, and the helpers that ship in the same barrel.
The Chatfuel API
The mental model behind the GraphQL API a generated app talks to — the hierarchy every operation traverses, the two automation surfaces that are not the same thing, and why the schema ships as a file.