Skip to content

Config JSONB — the agent & workflow config data dictionary

Status: Current | Last reviewed: 2026-09-21

The field-by-field reference for the two config JSONB blobs that hold every runtime definition in the platform: the agent pipeline on agent_versions.config and the workflow graph on workflow_versions.config (= workflow_configs.config). Read this when you need to know what a specific config key does and who reads it; read schema-guide.md first for the surrounding columns and the identity-vs-version split.

Both blobs are generated into canonical JSON Schema by generate-config-schemas.ts, which is the source of truth this doc tracks. Every field below exists in those schemas; when in doubt, grep agent-config.schema.json or workflow-config.schema.json.

GPT Live is discriminated by provider: "openai" and service: "GPT Live API". Its config.delegation_backend reuses the service-stage schema with type: "llm", so the nested backend configuration is validated against its own provider/service definition. See GPT Live configuration. config.tool_progress_messages_enabled is an optional boolean, default false: it controls authored per-tool progress speech in both Live delegation modes.

How the schemas are composed

The generator builds each schema from three sources of truth so they cannot drift from the code:

Source Feeds How
Hand-authored envelope (in the generator) Top-level keys + nested branches (Settings, Transfer, OutputLane, …) Kept in lockstep with pipeline-types.ts (AgentVersionConfig) and workflow-types.ts (WorkflowConfig)
50 service-definition JSONs (services/) Per-stage config Each becomes a branch of an allOf/if-then discriminated on (provider, service)
23 workflow node manifests (manifests/) Per-node config Each becomes a branch of an allOf/if-then discriminated on type

Both schemas declare a $id under https://trueserve.ai/schemas/ (agent-config.schema.json, workflow-config.schema.json) and use JSON Schema draft-07. Every leaf property carries a non-empty description — the schema doubles as the data dictionary, and the generator's description gate fails without one.

Validation is non-blocking. At publish time schema-validate.ts runs the config through ajv and surfaces mismatches as warnings only, layered on top of the imperative validators (validate-agent-config, workflow-validation.ts) — it never gates a save, so live configs that predate a schema change are not blocked. The CI workflow config-schema-drift.yml fails if the committed schemas differ from a fresh generation or any property lacks a description.

Note: the discriminated config branches are open (additionalProperties: true). An unrecognised (provider, service) or type matches no if, so the open config still accepts it — known stages/nodes validate precisely without rejecting newly-added ones.

Two validation tiers: structural vs buildability

"Is this config valid?" has two distinct answers, enforced by two tiers that share one source of truth and cannot disagree with the runtime:

Tier Question Source of truth Where it runs
Structural Are the field shapes/types/enums right? The generated agent-config.schema.json ai-manager (ajv, in the editor + at publish) and ai-orchestrator (jsonschema, in preflight) — the same file
Buildability Will the agent actually build + start a session? The real pipeline builder ai-orchestrator preflight (preflight.py)

Structural validity does not imply the agent will run — credentials, provider/service mapping, and per-wrapper config rules live outside the schema. The buildability preflight closes that gap: ai-manager's agent editor POSTs to POST /api/agents/[agentId]/preflight → the orchestrator's HTTP /preflight → preflight_agent, which runs the agent's stages through the same building blocks the live build uses — get_service_mapping, ServiceRegistry.validate_service_config, and get_api_key (credential resolution) — but stops before wrapper.create(), so it resolves and validates without opening any provider/MCP sockets ("resolve, don't connect"). Because it reuses the real builder, a preflight ok can't drift from what a real test does.

It returns { ok, errors[], warnings[] } with each issue tagged by gate: structural (shape / missing provider+type), service_mapping (unknown (provider, type, service)), service_config (wrapper validate_config rejected it), credential (the stage's integration_id / env var resolves to no key), or tool_ref. The editor's test buttons (voice call + chat) stay disabled while ok is false, showing the first error as the reason — so an agent that can't start can't be tested. The gate it does not make: ok: true means the session will start, not that the conversation is semantically good (a key present but rejected by the provider only surfaces on a live connect). See universal-pipeline-builder.md.

"Reuses the real builder" means the builder for that stage

get_service_mapping (service_constants.py) is the global (provider, type, service) → wrapper-key table, and it is the right one for main-pipeline stages. It is not the only one: TranslationPipelineBuilder resolves the stages inside config.translation.flows.{incoming,outgoing}.pipeline through its own TRANSLATION_SERVICE_LOOKUP, which both adds translation-only services (Phrase Splitter → PhraseSplitterProcessor, LLM Translation → LLMTranslationProcessor) and redirects a shared one (ElevenLabs WebSocket API → FastElevenLabsTTSService, a lower chunk_length_schedule for faster translated audio). The two tables can't be merged for exactly that reason: the same triple must resolve differently depending on which builder owns the stage.

Preflight therefore picks its resolver off the flow marker _iter_stages already yields — get_translation_service_mapping for a flow stage, get_service_mapping otherwise. Using the global table for every stage made preflight report service_mapping errors for the two trueserve stages of a translation agent that builds and runs fine, so ok was permanently false and the editor's voice + chat test buttons were disabled for every cascaded (STT → split → translate → TTS) translation agent. Single-stage S2S translation agents were unaffected because their triples (openai/s2s_translation/Realtime Translate, google/s2s_translation/S2ST) happen to exist in both tables — which is why the failure looked agent-specific rather than structural. Note the translation resolver never raises: an unknown triple falls through to the stage's own service name, and the registry gate is what rejects it — so a bad flow stage still blocks, just at service_config rather than service_mapping, mirroring where the live build fails. Regression coverage: test_preflight_translation_mapping.py.

Agent config — agent_versions.config

Source of truth: AgentVersionConfig in pipeline-types.ts. Top-level keys:

Field Type Meaning Read by
$schema string Optional URL of the schema, stamped on newly-saved configs. —
agent_type enum Legacy runtime discriminator (voice_ai, voice_augmentation, agent_assistant, translation_agent, text_chat). Derived from agents.subtype; the orchestrator still reads it. ai-orchestrator
pipeline PipelineEntry[] The core of the agent: ordered stages, parallel groups, swimlane groups. ai-orchestrator (build), ai-manager (canvas)
settings Settings Global pipeline settings (see below). ai-orchestrator
output_lanes { [id]: OutputLane } Named transcript/analysis output lanes, each with parallel branches. ai-orchestrator
translation UnifiedTranslation Bidirectional translation flows. Translation agents only. ai-orchestrator
copilot CopilotConfig The prescriptive Agent Assist branch. Copilot agents only — and on those it holds the whole behaviour, with pipeline down to one transcription stage (see below). ai-orchestrator, ai-manager
resilience Resilience Fallback-pipeline + health-check behavior. ai-orchestrator
lifecycle Lifecycle Workflow ids to run on conversation start/end (canonical home — see below). ai-orchestrator
avatar Avatar Photorealistic avatar rendering config. surface-app, ai-orchestrator
transfer Transfer Warm-transfer / consult config. ai-orchestrator
local_action_tool_ids string[] Copilot-only: host_action tool UUIDs rendered as clickable suggestion buttons in the host. surface-app/host
name, description, extension string Deprecated mirrors of agents.* / stage config. Stripped from agent configs by 004; nothing reads them. —

Warning: panel-scoped top-level agent-config sections (transfer, resilience, local_action_tool_ids, copilot) ride an opaque misc branch through the collab Yjs allow-list. A new top-level agent key is dropped on every autosave unless added to MISC_ROOT_FIELDS in both copies of pipeline-shape.ts. See universal-pipeline-builder.md.

ServiceStage (a pipeline entry)

One processing node in the pipeline. pipeline entries are a ServiceStage, a legacy parallel group (array of branches, each an array of stages), or a SwimlaneGroup. Stages run in array order; nested arrays run concurrently.

Field Type Meaning Read by
provider string Provider slug (openai, google, elevenlabs, deepgram, aws, …). Required. ai-orchestrator
type string Stage kind: stt, llm, tts, s2s, s2s_translation, translation, stt_suggestion, assistant_agent, processor, utility. Required. ai-orchestrator
service string Specific service variant (matches a service-def service field, e.g. Streaming Completions). ai-orchestrator
id string Stable slug derived from stage_name; the injection-target name and canvas node id. ai-orchestrator, ai-manager
stage_name string Human label shown on the canvas node. ai-manager
description string Author note rendered in the node body (documentation only). ai-manager
integration_id string Credential integration (integrations.id); falls back to the tenant provider default when omitted. ai-orchestrator
tools string[] Tool refs the stage's LLM may call: a tool_config UUID, builtin:<id>, or inline:<id>. ai-orchestrator
position {x,y} Canvas coordinates (editor layout only; no runtime effect). ai-manager
config object Service-specific config, discriminated on (provider, service) — see below. ai-orchestrator

The config shape is selected by an allOf/if-then branch (one per of the 50 service definitions). Two cross-cutting config keys are added to every stage branch by the generator:

config.* key Meaning Read by
builtin_tool_configs Rich per-node config for selected built-in tools, keyed by unprefixed built-in id — message_injection (default_priority, trigger_response, wait_for_tts_end) and ivr_navigation (goal_mode, goal, goal_template). ai-orchestrator
capability_configs Per-capability config for registry capabilities (capability:<slug> refs in config.tools), keyed by slug. The value shape is the capability manifest's config_schema (tenant-defined), so it is validated dynamically at publish (warnings only) rather than in the static schema. DRAFT-only in practice: publish expands the refs and this block travels along untouched. See capability packs. ai-manager (publish expander)
ces_integration Google CES-only surface: mcp_url_catalogs, warm_transfer_profile, tool_dispatch[], child_agents[] baked into the generated CES MCP URL. ai-orchestrator, agent-host

On PUBLISHED versions only, the root may carry _capability_provenance (keyed by slug: definition_id, version, manifest_snapshot) — stamped by capability-expander.ts when publishAgentVersion expands capability: refs into inline tools / logic / prompt text / variables. Drafts never carry it, and collab never reads published rows, so it deliberately stays out of MISC_ROOT_FIELDS.

Note: a handful of stage-config params are polymorphic — input_audio_transcription (bool / object / null), turn_detection (enum / object / null), and tools (string refs or inline function-definition objects). The schema emits the accurate oneOf; model/voice/language are open strings (the service-def options list is the curated UI set, not a validation constraint).

SwimlaneGroup

The modern parallel construct (a pipeline entry with type: "swimlane_group"). Branches run concurrently with shared turn-taking and a join policy.

Field Type Meaning
swimlanes[] array Parallel branches: each { stages: ServiceStage[], _swimlane: {id,label,color,turn_priority,gating} }. _swimlane is editor metadata; gating:"off" bypasses the turn gate for analysis-only lanes.
join_policy.audio enum mix (PCM-sum), first_speaker, or drop. Default mix.
join_policy.transcripts enum merge or keep_separate. Default merge.
join_policy.cancel_propagation enum any (OR) or all (AND). Default any.
join_policy.turn_strategy enum none, explicit_protocol, or barge_in. Default none.
cross_feeds[] array Inter-swimlane text feeds: {source_swimlane, target_swimlane, frame_types[], template?, debounce_ms?, finalized_only?} — pipe one lane's frames into another lane's LLM context.

OutputLane / LaneBranch

output_lanes is keyed by lane id; each value is an OutputLane that taps the main pipeline and runs parallel processing branches.

Field Type Meaning
OutputLane.enabled bool Master switch for the lane.
OutputLane.branches[] LaneBranch[] Parallel processing branches.
OutputLane.source_node_index int Main-pipeline node index this lane taps (per-branch can override).
OutputLane.frame_types[] string[] Frame types flowing into the lane (e.g. transcription, metadata).
OutputLane.output_type enum output (shown in Transcripts Out) or analysis (processed, not surfaced).
LaneBranch.processors[] ServiceStage[] Sequential stages for the branch.
LaneBranch.label string Branch label (e.g. Sentiment, Compliance).
LaneBranch.injection object Local injection {target, prompt}: route messages to this branch and prompt its LLM.
LaneBranch.transcript_filter object {transcript_types[], speaker_roles[]} filtering which transcripts the branch processes.

_legacy_essentials (on both) is a backward-compat toggle that auto-appends essential frame types when absent/true; new configs set it false.

UnifiedTranslation / TranslationFlow

Field Type Meaning
flows.incoming TranslationFlow Caller→agent direction.
flows.outgoing TranslationFlow Agent→caller direction.
TranslationFlow.pipeline[] ServiceStage[] Stages for the direction (STT→translation→TTS, or a single S2ST stage). The only required field.
TranslationFlow.echo_original_audio bool Echo the untranslated audio at whisper volume.
TranslationFlow.echo_volume number Echo volume percent (5–50, default 25).

Warning: the language pair's canonical home is now the translation / S2ST stage's own config (config->>target_language, echo_target_language, and the stage's voice selection), not the flow. The flow-level source_language, target_language, and voice_config are deprecated legacy fields, used only by cascaded STT→translate→TTS flows and otherwise collapsed into the stages. Do not author the pair at flow level for S2ST / realtime translation stages.

Settings (config.settings)

Source of truth: UniversalPipelineSettings in pipeline-types.ts.

Field Type Meaning Read by
audio object Transport audio I/O: format (pcm16/pcmu/pcma), sample_rate, channels. pcm16 for WebRTC; G.711 for telephony. ai-orchestrator
compliance object {enabled, redact_pii} — PII redaction of transcripts and stored messages. ai-orchestrator
lifecycle Lifecycle Mirror of top-level config.lifecycle. No longer read — 004 drops this nested key. —
text_turns object Turn-taking for multi-branch text_chat agents: mode (concurrent_serialized/sequential_shared), order (completion/config), allow_silence. Consumed only when text_chat with 2+ branches. ai-orchestrator
context_summarization bool | object Auto context summarization (off by default). true uses defaults; an object overrides max_context_tokens (8000), target_context_tokens (6000), max_unsummarized_messages (20), min_messages_after_summary (4). Cascaded voice + text only; S2S manages context server-side. ai-orchestrator
swimlane object Simultaneous-speech mixing config for 2+ parallel S2S/realtime branches; drives TurnAwareMixer + SwimlaneAudioTagger. ai-orchestrator
rate_limits array Named rate-limit profiles referenced by workflow llm_agent nodes. Agent configs rarely set this. async-agent

Resilience, Avatar, Transfer

$def Key fields Read by
Resilience enabled, fallback_pipeline_id (agent id), health_check_strategy (none/on_demand/proactive), health_check_interval_seconds. ai-orchestrator
Avatar enabled, provider (azure_avatar/bey), Azure: integration_id/character/style/voice/background_color/background_image; BeyondPresence: bey_avatar_id/bey_integration_id. surface-app, ai-orchestrator
Transfer enabled, provider (genesys_byoc/webex_byova/scv_native/genesys_cloud), consult_agents[], hold_mode (music/listen_only/talk_and_listen), post_merge_mode (drop_both_agents/keep_agent_a/keep_both), consult_timeout_sec, recording, role:"consult". ai-orchestrator
Lifecycle on_start, on_complete — workflow_configs.id (or null) to run on conversation open/end. Canonical at top level; settings.lifecycle is dead. ai-orchestrator

Injection and Ivr are defined in the schema's $defs but are not top-level fields on AgentVersionConfig — that config lives per-stage under config.builtin_tool_configs. They are absent from MISC_ROOT_FIELDS accordingly, and pipeline-shape.test.ts asserts a top-level injection/ces/warm_transfer/ivr key does not survive the Y.Doc round-trip.

Agent Logic (variables, per-stage logic / tool_logic)

$def Key fields Read by
AgentVariable (top-level variables[]) name (snake_case, session-variable namespace), type, source (mutable/linked), default, linked_to, description (required). In MISC_ROOT_FIELDS (both copies). ai-orchestrator (Phase 3+), editor
StageLogic (pipeline[N].config.logic) rules[] (trigger/condition/actions), response_guards[] (check/on_violation/enforcement/strict). ai-orchestrator (Phase 3+)
ToolLogic (pipeline[N].config.tool_logic.<toolName>) available_when (fail closed), unavailable_message, bind (schema-stripped params), capture. Sibling of tools, never a mutation of it. ai-orchestrator (Phase 3+)

Full semantics, grammar, and validation rules: agent-logic.md.

The copilot branch (Agent Assist)

Source of truth: CopilotConfig in pipeline-types.ts. Present on subtype=copilots agents instead of hand-wired suggestion stages, and unique among the top-level branches in that it holds the whole behaviour of the agent: config.pipeline carries exactly one real stage (transcription) and everything else is planned from here. See copilots.md for the runtime.

Field Type Meaning Read by
transcription.enhancement object Optional transcript rewrite before any type reads it: enabled, llm_provider, llm_model, integration_id, context_window, enhancement_mode (domain_correction default | full_enhancement), system_prompt. full_enhancement also rewrites grammar, making the transcript a paraphrase. ai-orchestrator
transcription.glossary.terms[] array {term, hint} domain vocabulary fed to enhancement and (opt-in) translation. ai-orchestrator
variables Record<string,string> Session-start bindings ($var:NAME) usable in every copilot prompt. ai-orchestrator
gate object The shared actionability gate: enabled, llm_provider, llm_model, integration_id, min_utterances, debounce_seconds, context_window, runs_on, prompt_override. ai-orchestrator
types[] CopilotTypeConfig[] One configured behaviour each — see below. ai-orchestrator, ai-manager
summarization.on_transfer object {enabled, llm_provider, llm_model, integration_id, system_prompt, card} — publishes live, pinning a SummaryCard while the call is still up. ai-orchestrator
summarization.post_call object Same shape plus optional response_schema (custom object fields), card_bindings (card property → response.<path>), and context_window (turns; default all), extracted during teardown; persisted as a copilot_summary conversation event and replayed on the historical SSE stream. ai-orchestrator, conversation-api

types[] entries are a discriminated-ish union on kind (suggested_answers | coaching | custom | legacy translation | form_filling). Shared fields: id, kind, label, runs_on (agent|customer|both), enabled, card, llm_provider, llm_model, integration_id, bypass_gate, context_window, auto_summarize_context, min_utterances, debounce_seconds, temperature, layout_region. Per-kind: coaching → system_prompt, tool_ids[], inline_tools[], tool_logic (normal per-tool bindings/conditions/captures); custom → same plus response_schema and card_bindings; suggested_answers → prompt_override, required knowledge_tool_ids[], inline_tools[], tool_argument_mapping, and query_refinement (llm_provider, llm_model, integration_id, system_prompt, response_field_descriptions); translation → target_language, glossary_ref, render; form_filling → forms[] + allow_dynamic.

Every prompt-bearing branch accepts response_field_descriptions: JSON Pointer → description text, applied only to existing fields. Query refinement always returns {query: string}, used in Knowledge input mappings. Context windows are in turns. LatestMessage, LatestCustomerMessage, LatestAgentMessage, ConversationHistory, and answer-only KnowledgeSources are reserved runtime variables, not session-start bindings.

Four properties of this branch are contractual, not conventions:

  • types[] being a list is the discriminator. is_copilot_pipeline_config keys on it, and an empty list still matches — a copilot with nothing enabled is a real agent that transcribes and suggests nothing. The legacy hand-wired shape carries the same agent_type: 'agent_assistant' with no copilot key, so it keeps building through UniversalPipelineBuilder.
  • card is <catalog-uri>#<ComponentName>. Built-in card workers use its props_schema as their response contract. Custom Copilot and post-call summaries can define an independent response_schema and map its values with card_bindings; mapped props must validate against the card schema. An unresolvable ref means the worker is skipped, not downgraded. translation is the exception (inline kind, built-in schema, never consults a card).
  • id is minted once at add time and never re-derived. The A2UI surface_id is copilot-<id>, and a surface replaces in place only while its id is stable, so re-deriving from a renamed label stacks a new card per rename.
  • copilot must stay in MISC_ROOT_FIELDS in both copies of pipeline-shape.ts (see the warning above). It is a panel-scoped branch, so it rides the opaque misc Y.Map — and an unlisted key is dropped on every autosave with the change visible in the editor.

Workflow config — workflow_versions.config / workflow_configs.config

Source of truth: WorkflowConfig in workflow-types.ts. Top-level keys:

Field Type Meaning Read by
$schema string Optional schema URL, stamped on newly-saved configs. —
name string Display name. Authoritative copy is the table row (workflow_configs.name); this JSONB mirror is optional — ~1/4 of live configs omit it. ai-manager
description string Human-readable workflow description. ai-manager
execution_mode enum sync (caller blocks; forbids wait/human_review/conversation_actions), async (returns execution_id), or batch (implies async; events buffered + flushed). Unset = sync. async-agent
settings WorkflowSettings Runtime limits, retry policy, rate limits, batch-mode config. async-agent
phases WorkflowPhase[] Canvas grouping containers (no runtime effect). ai-manager
nodes WorkflowNode[] The workflow nodes. Required. async-agent
edges WorkflowEdge[] Directed edges with optional conditional routing. Required. async-agent
triggers WorkflowTrigger[] Versioned trigger definitions; projected to trigger_rules on publish. ai-manager (publish)
input_parameters WorkflowParam[] Declared inputs (test panel + trigger field-mapping). async-agent
output_parameters WorkflowResponseVar[] Declared outputs (alias of response_variables). async-agent
response_variables WorkflowResponseVar[] Outputs exposed to conversation lifecycle hooks ({{lifecycle.<name>}}). async-agent, ai-orchestrator
inline_tools array Workflow-local tool defs (Python/API/knowledge), referenced as inline:<id>. Knowledge entries carry source_slug but never the connection (server_url/transport/token) — the MCP URL is derived at runtime from the tenant's Knowledge settings. async-agent, agent-host
communication_templates object Reusable SMS/email templates keyed by name; referenced by notification nodes via template_ref. async-agent
tool_definitions array Legacy workflow-exposed tool definitions. async-agent

Warning: as with agent configs, the collab Yjs shape is an allow-list. A new top-level WorkflowConfig key is dropped on every autosave unless added in both directions to workflow-shape.ts. This silently ate triggers and execution_mode once.

WorkflowNode shared fields

Field Type Meaning
id string Unique node id within the workflow. Required.
type enum Node type (see table below); selects the runtime handler and the config shape. Required.
label string Human-friendly name (never a lookup key — id stays fixed).
goal string Optional description of the node's purpose.
phase string Optional phase id (canvas grouping).
parent string Parent foreach/subworkflow node id (nested body nodes).
provider string LLM provider hint.
integration_id string Credential integration id used by the node.
position / size object Canvas layout only.
config object Per-node-type config, discriminated on type — see below.

WorkflowEdge is {from, to, condition?, kind?, label?}: use START/END pseudo-nodes for entry/exit; condition is the router output id that selects the edge; kind:"body_ref" marks a layout-only foreach/parallel body edge skipped at runtime.

Node types

The config shape is discriminated on type. The 23 types carried in the generated schema (one per manifest):

type Purpose
llm_agent Run an LLM with an instruction, optional tools, optional structured output.
router Branch into named outputs by per-output expression (first truthy wins).
tool Execute a registered tool directly without an LLM.
code Run sandboxed Python (async def execute(ctx)). Retired in the editor; loads as a Tool node selecting an inline Python tool.
http_request Call any HTTP endpoint with retries, timeout, integration-backed auth.
assignment Write workflow variables (set/append/prepend/concat/increment).
conversation_actions Create/reuse a conversation, optionally start a live session, inject an instruction, mint a share code.
notification Send a message via an integrated channel (SMS, email, push).
human_review Suspend until a human approves or rejects.
wait Suspend until a duration elapses or an event arrives.
foreach Run a nested body once per item in a list/dataset (durable, bounded concurrency).
parallel Deprecated. Use foreach with mode:"parallel".
subworkflow Call another workflow as a subroutine (inline or ref; depth-capped at 2).
ocr_extract Extract text/tables/forms/structured data from a document via OCR, LLM vision, or both.
transcribe Transcribe an audio file via a managed STT provider.
pii_redaction Detect and redact PII from a string before downstream nodes.
reasoning_step Execute a single reasoning step with typed output and retry.
reasoning_chain Sequence multiple reasoning steps with shared state and a cost budget.
plan_extract Extract a structured plan from conversation messages.
score_generation Compute a numeric score from workflow fields (local weighted average or managed AutoML).
salesforce First-class deterministic Salesforce step (create/update/query/publish), no LLM.
scheduled Legacy delay node. Prefer wait with a duration condition.
passthrough No-op fallback for unknown node types.

Note: TS NODE_TYPES also defines note (a canvas-only annotation, never traversed at runtime). It has no manifest, so it is not in the generated schema's type enum and its config (text, color) is not discriminated.

Router node — canonical shape

The router config is { outputs: [{id, label, expression?}] }. Outputs are evaluated in order; route_value = the first match's id, which equals the outgoing edge's condition, so the target node is inferred entirely from the edge you drew on the canvas. The legacy condition_field / routes shape was migrated to outputs[] by 004 (and the Python back-compat branch in router.py removed) — it is no longer supported at runtime.

ocr_extract node — canonical shape

Canonical fields: ocr_integration_id, document_source (url/base64/s3_uri/gcs_uri/azure_blob_url/minio_key), document_reference, processing_type (ocr/llm/both), aws_features (and aws_queries, gcp_processor_id/gcp_location, azure_model_id), plus the LLM side (llm_integration_id, llm_model, llm_prompt, llm_output_schema, llm_input_mode). The legacy input{} / integration_id / features / output_schema shape was migrated by 004 (matching the Python normaliser removed in ocr_extract.py).

WorkflowSettings, triggers, params

$def Key fields
WorkflowSettings max_runtime_minutes, max_total_llm_calls, timeout_action, retry_policy{max_retries,backoff_base_seconds}, llm_execution, rate_limits[], batch_mode{enabled,flush_cron,interval_seconds,max_window_seconds,max_batch_size,group_by,llm_defaults}.
WorkflowTrigger kind (api/agent_tool/conversation_start/conversation_end/schedule/salesforce/gcp_pubsub/aws_eventbridge), enabled, label, condition. conversation_*/schedule/salesforce/gcp_pubsub/aws_eventbridge project trigger_rules rows on publish; api/agent_tool do not.
WorkflowParam name, type, description, required, is_input, default, enum, items. Referenced as {{input.<name>}}.
WorkflowResponseVar name, source (dot-path or JSONata), source_mode (path/jsonata), description, type.

How to regenerate

cd shared/service-definitions
npx tsx generate-config-schemas.ts            # write the 2 JSON schemas + generated-schemas.ts
npx tsx generate-config-schemas.ts --check     # exit 1 if committed files drift (the CI gate)
npx tsx generate-config-schemas.ts --report     # list properties missing a description, don't fail

A plain run writes agent-config.schema.json, workflow-config.schema.json, and the bundler-safe TS module generated-schemas.ts that the ajv validator imports. Re-run after editing a service definition, a node manifest, or the envelope in the generator — otherwise config-schema-drift.yml fails CI.

See also

Copilot form instances and applicability

CopilotType.catalogs and CopilotSummarizationTarget.catalogs are selected catalog URI arrays. Form Filling uses CopilotType.cards as its available card-reference palette. CopilotForm.card chooses one reference (implicit when the palette has one card), and card_bindings maps display fields to selected-card properties. repeat_mode is once (default) or repeatable; completion_mode is agent_confirmed (default) or required_fields. Each configured form gets its own worker, with instance state held by the active pipeline. The generated schema describes all these fields.

The runtime adds the applicable/reason/nullable-result response envelope; it is not authored into response_schema. response_field_descriptions keys under /envelope/properties/ override applicability descriptions. Other keys continue to address the result schema. SDK dismissal policy is presentation state and is not stored in the agent's Copilot configuration. See Copilots.

Inline tool testing

Inline Python/API/Knowledge tool definitions can carry output_schema and a version-1 testing object. The same data-only mock schema is used for library-tool revisions. Simulation submission pins these fields together with the selected agent version. See Tool testing.

Saved conversation tests

agent_test_cases.persona contains the simulated caller's name, goal, emotional state, language and optional opening line, background and facts. Submission copies the caller into agent_sim_batches.spec.personas and snapshots selected case revisions, expected outcomes, turn limits and linked goldens under spec.test_cases. spec.test_case_ids preserves the selection for reruns. These are evaluation records; the agent's runtime configuration is pinned separately in target. See Agent evaluation API.