/api/tfu-live-agents module. Ordinary agents keep their existing creation body and
purpose types. Runtime is not a fourth outreach/inbound/appointment purpose.
Use the returned tfu_live:<profileId> public id on the TFU Live routes.
The server verifies the stored tenant-owned identity; an id prefix grants no
access. Runtime conversion and mixed ordinary/TFU authored bodies are
refused.
These changes are local development code, not a production publication.
Agency owners can also create agents from the dashboard, using Build with AI
or Configure myself. The same sub-account ownership and resource checks apply
to manual edits and typed or spoken co-authoring. project_user access does not
permit creation. Provider administration remains restricted to staff.
Prerequisites
- An agency API key with
agents:readto inspect an agent oragents:writeto create, edit and prepare it. Write scope also covers reads. - A connected sub-account belonging to that key’s agency. A narrower credential
location binding still applies. Supplying another
locationIddoes not grant access. - An authorised test environment and synthetic records. A local server can still use a shared development database and external providers.
Authorization: Bearer YOUR_API_KEY, as described in
Authentication. The examples use placeholder IDs, not working
customer records. No staff credential or internal service key is required.
Step 1: Create an empty draft
Send this body to Create agent with?locationId=YOUR_LOCATION_ID:
id using letters, digits, underscores or hyphens, up to 100
characters. Keep it if you lose the response: read that ID before retrying.
Retry creation with the same id and original body to finish an interrupted
campaign attachment. The retry keeps an existing campaign and its settings.
Campaign and private cadence writes commit together, so a failed attachment
cannot leave a partial campaign or duplicate cadence. A saved provider draft
remains available for the same-id retry; creation is not reported as complete
until the campaign is confirmed. TFU_LIVE_CAMPAIGN_PENDING reports that recoverable partial creation. TFU Live does not use the ordinary agent’s Idempotency-Key replay contract.
An existing conflicting ID returns an error rather than creating another agent.
The response is 201 with data.agent and data.campaign. New agents, including
empty drafts, automatically receive a linked paused campaign and a private Power
Dialer cadence, and start with two workflows, Schedule a callback and Stop
contact, unless the body already brings a workflow that schedules an AI call
or puts the lead on DND. data.campaign.id is the campaign identifier; profileId is its
internal TFU Live profile binding. Caller numbers and trigger tags start empty.
Choose them in Settings and the Brain trigger before going live.
Read the actual data.agent object for id, ifVersion, brain, voice and
setup. A draft has provisioningPolicy: "explicit". Creating and editing this
draft does not provision provider agents or activate a campaign.
Alternatively, supply id, name, brain and voice together to create a
complete agent. Complete creation starts setup immediately. A successful create
still does not mean setup has finished.
Or start from a Brain template, a ready-made agent: send id, brainTemplateId
and the values it needs (a calendar, who takes transfers) to create an explicit
draft that already has its workflows and a starting prompt. List them with
List TFU Live Brain templates;
the workflows contract describes
each and what it needs.
Step 2: Discover only the capabilities you need
Read Discover TFU Live capabilities at/api/tfu-live-agents/tfu_live:example_agent/brain/catalog?locationId=YOUR_LOCATION_ID.
An agent’s abilities are workflows: each has a name (the AI’s tool name),
a description (when the AI should run it) and steps built from nodes. The
catalog’s data.workflows lists every node with its settings (in words and as
JSON Schema), outputs, timing and the arguments it takes, the templates to start
from (Live transfer, Book appointment, Cancel appointment, Human assistance, Stop
contact, Check tag, Add tag, Schedule a callback, Check service area) and which
of their settings must be filled before saving, the path rules and the limits.
data.subAccount says which CRM the sub-account uses: on the native CRM
(nativeCrm: true) there are no tags, so tag nodes are refused. The catalog is
not an agent’s saved configuration; read the agent separately for its current
state. Create a draft before requesting its catalog. The
workflows contract describes every shape.
data.capabilities is the short index of the tool groups that stay tools. Add
group=outreach to retrieve that group’s tool schema, configuration and business
questions. supported reports the connected runtime’s support, not business readiness.
The catalog also lists
voices and background rooms. Do not invent names or
infer what a voice sounds like from its name.
Resolve calendars, tags, custom fields, pipelines, reps and teams with
Look up TFU Live resources
(GET /api/tfu-live-agents/{id}/resources/{kind}). It reads the same lookups a
save verifies against, with this module’s scope and sub-account checks. An
unavailable lookup (status: "unavailable") is unknown, not an empty list.
Calendars come from the sub-account’s CRM. A native sub-account lists its own
native calendars (source: "native"): they work in roleplay, but a real call
cannot book on them yet, so going live needs GoHighLevel. A GoHighLevel
sub-account lists its GoHighLevel calendars only (source: "gohighlevel"), and a
save there refuses a native calendar. sources reports each source on its own: a
source that could not be read is unavailable while the others are still listed.
Read data.agent.authoring.editable before editing an existing agent. A false
value with legacy_voice_contract, unrepresented_capability or
outdated_format in authoring.reasons means the API cannot represent that agent
losslessly; outdated_format is an agent saved before the workflow model. Edits and preparation return 409 until an explicit
migration is completed. Reading it does not change existing behaviour.
Step 3: Translate the business request into a reviewed edit
For “cover postal code 10001, explain the boundary elsewhere, and speak calmly”, send the complete authored object below to Update agent with?locationId=YOUR_LOCATION_ID:
ifVersion with the value from your last read. This is a complete
TFU Live authoring replacement, unlike the ordinary agent’s partial config
patch. To change one workflow without sending the rest, use
Replace TFU Live workflow
and its neighbours, which run the same checks. Preserve unrelated prompt text, capability configuration and existing
workflows. The response returns the next ifVersion. A workflow id is wf_
followed by 8 lowercase letters or digits; keep an existing workflow’s id when you
change it, so its tool keeps its history.
Brain text may remain incomplete while an explicit draft is being built. Voice
instructions must remain non-empty. Fields outside this authoring contract,
including model selection, runtime changes and campaign activation, are refused.
For appointments, build a workflow from the Book appointment template. Find
slots offers times from one calendar, or from ordered routing rules over collected
answers: the first matching rule’s calendar is used, an unknown answer is asked
for, and there is no default calendar, so add a last rule with is_set for a
catch-all. When one choice item decides, every one of its answers must choose a
calendar. Every calendar must be active in this sub-account. The calendar’s CRM
sub-account supplies its timezone at runtime; do not ask for an appointment
timezone. Collect information gathers the answers during the call, before
availability and booking; post-call extraction is too late for this decision.
Step 4: Prepare the exact saved version
Explicit drafts stay unprovisioned until you send this body to Prepare TFU Live agent at/api/tfu-live-agents/tfu_live:example_agent/prepare?locationId=YOUR_LOCATION_ID:
ifVersion, not authored fields. Preparation validates the saved
configuration and starts setup for that exact version. Read the agent again to
observe progress. Existing agents without the explicit draft policy start setup
when edited.
A 202 response means the request was accepted. setupStarted reports whether
setup was requested; setupError reports an edit saved without confirmed setup.
setup.status can be draft, queued, provisioning, ready,
provisioning_blocked or provisioning_uncertain. Inspect failureCode on a
blocked or uncertain revision before retrying. setup.revision and
setup.verifiedAt describe verified setup, not campaign activation.
An edit can be pending while the prior verified version remains in service.
Always use the newly returned ifVersion and the current setup.status; an old
verification timestamp does not make a pending edit ready.
To go back to an earlier save, send ifVersion and that save’s revision
number from the agent’s changeHistory to
POST /api/tfu-live-agents/{id}/restore. The authored text of that revision
comes back as a new revision, through the same save and setup as an edit.
History is never rewritten, and the last fifty saves can be restored.
Boundaries
- Creating, saving and preparing an agent do not create or activate a campaign. Campaign permissions and activation checks remain separate. Campaign settings stay shared; current customer TFU campaign mutation adapters remain incomplete. Ordinary outcome prompts and workflow graphs are intentionally not applicable, not aliases for Brain text.
- TFU Live create/get/update own complete authored revisions. Use
GET /api/tfu-live-agents?locationId=...for its list andGET /api/tfu-live-agents/{id}/operationsfor current runtime support. Clone, delete and split-test are not implemented for TFU. - The agent’s abilities are
brain.capabilityConfig.workflows, part of the complete authored aggregate. Each workflow is a tool for the AI: its name gives the tool name, its description is when to run it, and renaming it renames the tool. There are no special workflows; every node can be used in any workflow. Collect information is the only way the AI supplies inputs: its items become the tool’s arguments. A node with outputs ends its list: the steps after it go on its outputs. Tags are never chosen by the AI: Check tag, Add tag and Remove tag each hold one tag. A Transfer node has the outputs Connected, Nobody available and Not connected; a call makes one transfer attempt, a fallback transfer goes only on Nobody available, and after Connected only actions and Conditions may follow. Put on DND ends the lead’s journey, so nothing follows it. The catalog’sworkflowscontract lists the node formats and limits. Saving validates the workflows with the runtime validator but executes nothing, and refuses an invalid workflow with422, naming the workflow and step. Custom fields, pipelines and calendars a new or changed step names must exist in this sub-account. HTTPS webhooks also pass outbound URL policy. A webhook sends the call’s context (workflow,sentAt,ids,contact,call) plus itsfields, each from fixed text, a contact field, a call detail or a collected answer. Authentication headers must be secret: send{"secret":{"value":"…"}}once, and the value is stored encrypted and read back only as{"secret":{"id":"…"}}, which you send back unchanged to keep it. The formats workflows replaced (brain.hooks,followUps,outcomeSteering,customTools,appointments, per-tool settings such astransfer_callorcheck_area_code, and workflows keyed by tool id) are refused until the agent’s migration has run. - A Notify teammate node sending to Slack uses symbolic
mainoralertschannels, resolved by the runtime from the call tenant.authoring.bindingWarningsdistinguishes an unverified mapping from a ready integration. - Transfer destinations and team-channel mappings require existing authorised configuration. A Transfer node names its destination; it does not create one.
- Split/master authoring and provider-specific tuning are not supported by this contract. Voice delivery instructions do not implement numeric provider controls.
- The internal conversational builder retrieves focused authoring guidance and capability details through its own authenticated tools. Customer backends can use this guide and the discovery requests above; this API does not expose the internal builder conversation, voice session or arbitrary tool executor.
Shared campaign controls, separate authoring
Caller-number ownership, calling windows, timezones and concurrency use shared campaign services and checks. Follow-up timing uses the campaign-bound cadence. TFU Live still has its own verified profile and call lifecycle. Workflows run when the AI calls their tool, during the conversation. They are not the ordinary campaign outcome workflow graph. Some action implementations are shared, but this API does not accept that graph’s schema or claim its endpoint compatibility. Campaign association requires the TFU Live profile and the campaign binding to be visible to the runtime that validates them. A local setup with separate SaaS and voice databases does not prove this association works end to end. This change does not switch databases or migrate records.Handle errors
TFU Live errors use
{ "success": false, "error": "Explanation", "code": "…" },
and a workflow refusal also names workflowId, stepId and field. Branch on
code, never on the words: the codes are listed in the
workflows contract. Missing-scope
responses also identify requiredScope.
