automation-architecture

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Automation architecture

自动化架构

Goal

目标

Turn a customer use case into an exact, minimal Nexor configuration: named primitives with concrete field values, connected end to end. The deliverable is a configuration, not a recommendation.
将客户用例转化为精确、极简的Nexor配置:带有具体字段值的命名原语,端到端关联。交付成果为配置而非建议。

The three laws of decomposition

分解三定律

Apply these before choosing any primitive. They are not style preferences: each names the only shape the platform can gate, trigger, template, or verify. A design that breaks one is unreliable even when it demos correctly, because the platform cannot see the part that lives in prose.
在选择任何原语前先应用这些定律。它们不是风格偏好:每条定律定义了平台可管控、触发、模板化或验证的唯一形式。违反任意一条的设计即使演示正常也不可靠,因为平台无法识别仅存在于文字描述中的部分。

Law 1 — every piece of information the system needs is a variable

定律1 — 系统所需的每一条信息都是变量

If the build depends on knowing something, it exists as a named workflow field or as lead
metadata
. Never as prose in a prompt, never as "the agent will remember it from the conversation."
  • The agent must obtain it → workflow field,
    required: true
    , with
    extraction_hints
    .
  • An external system supplies lead identity/contact information → write
    first_name
    ,
    last_name
    ,
    email
    , and
    phone
    through the standard lead create/update contract. Never hide those values in metadata; metadata does not change Nexor's contact destinations.
  • An external system supplies other contextual information → put it directly in the lead's
    metadata
    JSON object. Keys may hold strings, numbers, booleans, null, arrays, or nested objects; the complete metadata object is injected into the next runtime agent prompt, so the agent can access every parameter and value without one field per key.
  • The agent must ask for, validate, normalize, or gate on externally supplied information → add a workflow field with
    metadata_key
    (and
    intake_value_map
    when needed) so metadata pre-fills the field instead of being asked.
    metadata_key
    ,
    options
    ,
    extraction_hints
    , and
    validation
    can only be written in the initial
    create_workflow
    call
    update_workflow_structure
    accepts just
    key
    ,
    label
    ,
    type
    ,
    required
    ,
    sort_order
    . Finish the variable ledger before creating the agent.
  • A tool produces it →
    llm_response_fields
    keeps it in the turn; a post-tool hook writes it to metadata when a later step needs it.
  • Gates read fields only.
    required_field_keys
    ,
    requires_all_fields
    , and
    transition_rules
    cannot see metadata.
  • Deterministic senders read metadata only. Status-automation
    args_template
    , webhook
    payload_template
    , and HTTP tool templates address
    {{lead.<path>}}
    /
    {{lead.metadata.<key>}}
    and cannot read collected field values. Anything an automation must transmit must be mirrored into metadata (post-tool hook or
    patch_metadata
    ) before the lead can reach the triggering status. The full reader/store matrix is in references/configuration-reference.md.
For every fact the design uses, name its key and its store. A fact that lives only in conversation history cannot gate a status, route a lead, fill a request body, or filter a job.
如果构建依赖某条信息,它必须以命名的工作流字段或潜客
metadata
形式存在。绝不能是提示词中的文字描述,也不能是“Agent会从对话中记住它”。
  • Agent必须获取该信息 → 工作流字段,设置
    required: true
    ,并添加
    extraction_hints
  • 外部系统提供潜客身份/联系信息 → 通过标准潜客创建/更新协议写入
    first_name
    last_name
    email
    phone
    。绝不能将这些值隐藏在metadata中;metadata不会改变Nexor的联系目标。
  • 外部系统提供其他上下文信息 → 直接放入潜客的
    metadata
    JSON对象中。键可存储字符串、数字、布尔值、null、数组或嵌套对象;完整的metadata对象会注入到下一次运行时的Agent提示词中,因此Agent无需为每个键单独设置字段即可访问所有参数和值。
  • Agent必须询问、验证、标准化或基于外部提供的信息设置门限 → 添加带有
    metadata_key
    的工作流字段(必要时搭配
    intake_value_map
    ),使metadata预先填充字段而非让Agent询问。
    metadata_key
    options
    extraction_hints
    validation
    只能在初始
    create_workflow
    调用中设置
    update_workflow_structure
    仅接受
    key
    label
    type
    required
    sort_order
    。在创建Agent前完成变量清单。
  • 工具生成该信息 →
    llm_response_fields
    将其保留在当前对话轮次;当后续步骤需要时,工具后置钩子将其写入metadata。
  • 门限仅读取字段。
    required_field_keys
    requires_all_fields
    transition_rules
    无法读取metadata。
  • 确定性发送方仅读取metadata。 状态自动化的
    args_template
    、webhook的
    payload_template
    和HTTP工具模板仅支持
    {{lead.<path>}}
    /
    {{lead.metadata.<key>}}
    ,无法读取已收集的字段值。自动化必须传输的任何信息,都必须在潜客到达触发状态前通过工具后置钩子或
    patch_metadata
    同步到metadata中。完整的读取/存储矩阵见references/configuration-reference.md
对于设计中使用的每一个事实,命名其键和存储位置。仅存在于对话历史中的事实无法设置状态门限、路由潜客、填充请求体或过滤任务。

Law 2 — every state change inside one agent is a status

定律2 — 单个Agent内的每一次状态变化都是一个status

If the agent's behavior, permissions, or obligations change at some moment, that moment is a status in that agent's pipeline. Never a "phase" described in the prompt, never a boolean parked in metadata.
Statuses are the only handle the rest of the platform can grab. A stage that is not a status is invisible to
workflow_tools.available_in_statuses
,
status_automations.on_status_key
, webhook filters on
to_status.key
,
timeout_config
,
transition_rules
/
required_field_keys
, background-job
workflow_filters.status_keys
, recontact
trigger_status_key
, and
assignment_config
.
Give each stage a
key
, a
label
, an
entry_hint
stating its entry criterion in terms of Law 1 variables, and an explicit gate. When field values fully determine the move, add
transition_rules.rule_groups
with
auto_evaluate: true
so the platform advances the lead instead of depending on the agent calling
set_lead_status
.
Express every gate as
required_field_keys
(or
requires_all_fields
) plus
transition_rules
.
variable_refs
is not writable through MCP
— it is a dashboard display hint, so a design that relies on it has no gate at all.
review_agent_system_plan
enforces this law for you: any non-initial status with neither
entry_hint
nor
transition_rules
comes back as a clarification question.
如果Agent的行为、权限或义务在某个时刻发生变化,该时刻即为该Agent流程中的一个status。绝不能是提示词中描述的“阶段”,也不能是存放在metadata中的布尔值。
Status是平台其他部分可操控的唯一入口。未定义为status的阶段对
workflow_tools.available_in_statuses
status_automations.on_status_key
、基于
to_status.key
的webhook过滤器、
timeout_config
transition_rules
/
required_field_keys
、后台任务的
workflow_filters.status_keys
、重触达的
trigger_status_key
assignment_config
完全不可见。
为每个阶段设置
key
label
、基于定律1变量描述进入条件的
entry_hint
,以及明确的门限。当字段值可完全决定流转时,添加
transition_rules.rule_groups
并设置
auto_evaluate: true
,使平台自动推进潜客流转,而非依赖Agent调用
set_lead_status
将所有门限表示为
required_field_keys
(或
requires_all_fields
)加上
transition_rules
variable_refs
无法通过MCP修改
— 它只是仪表盘显示提示,因此依赖它的设计相当于没有门限。
review_agent_system_plan
会强制执行该定律:任何非初始status若既无
entry_hint
也无
transition_rules
,会返回澄清问题。

Law 3 — every switch of agent identity happens at a boundary status that transfers

定律3 — 每一次Agent身份切换都发生在可转移的边界status

Changing tone, persona, goal, prompt content, tool set, channel mix, or contact intensity means a different agent. The switch is never made inside a prompt. It is made by a boundary status the lead exits through:
  • Terminal handoff (default):
    is_terminal: true
    plus
    transfer_config: { "target_workflow_id": "<real id>" }
    . This is the only shape that auto-fires a transfer. Every agent path checks
    is_terminal
    before reading
    transfer_config
    , so a non-terminal status with a
    transfer_config
    never fires
    — the config saves cleanly and silently does nothing.
  • Never name a boundary status
    future_*
    ,
    contact_later
    , or
    colder
    .
    Those keys are treated as soft terminals and are excluded from the terminal side-effect path before
    transfer_config
    is read, so the transfer is skipped even on a correctly terminal status. This is the most silent failure in the whole surface.
  • Pause boundary:
    pause_bot: true
    when the handoff is executed out of band — a background job's
    workflow_transfer
    /
    force_transfer
    action, the one-off transfer API, or a human. A pause boundary must name its executor or the lead sits silent forever. It is safe to build on:
    pause_bot
    is a status flag and does not set
    workflow_runs.is_paused
    , so a job with the standard
    exclusions.skip_paused: true
    still picks these leads up.
Either shape ends the source agent's ownership at the boundary: exactly one agent is live per lead. The target always starts at its own initial status, its cadence starts over, and the source's collected fields travel as a read-only transfer-chain snapshot.
Forbidden shapes: a prompt that says "once qualified, switch to a closing tone"; a tool whose purpose is to change the agent's persona; two agents live on the same lead; a transfer aimed at a specific status inside the target.
改变语气、角色、目标、提示词内容、工具集、渠道组合或触达强度意味着使用不同的Agent。切换绝不能在提示词内部完成,必须通过潜客退出的边界status实现:
  • 终端移交(默认): 设置
    is_terminal: true
    并搭配
    transfer_config: { "target_workflow_id": "<真实ID>" }
    。这是唯一能自动触发转移的形式。每个Agent路径在读取
    transfer_config
    前都会检查
    is_terminal
    ,因此非终端status即使配置了
    transfer_config
    也永远不会触发
    — 配置会成功保存但静默无效。
  • 绝不能将边界status命名为
    future_*
    contact_later
    colder
    这些键会被视为软终端,在读取
    transfer_config
    前就被排除在终端副作用路径之外,因此即使status配置正确,转移也会被跳过。这是整个系统中最隐蔽的故障点。
  • 暂停边界: 当移交通过外部执行时设置
    pause_bot: true
    — 比如后台任务的
    workflow_transfer
    /
    force_transfer
    操作、一次性转移API或人工操作。暂停边界必须指定执行者,否则潜客会一直处于静默状态。该形式是可靠的:
    pause_bot
    status标志,不会设置
    workflow_runs.is_paused
    ,因此带有标准
    exclusions.skip_paused: true
    的任务仍会选中这些潜客。
两种形式都会在边界处终止源Agent的所有权:每个潜客同时只能有一个活跃Agent。目标Agent始终从自身初始status开始,其触达节奏重新启动,源Agent收集的字段会作为只读转移链快照传递。
禁止形式:提示词中写“一旦合格,切换为成交语气”;以改变Agent角色为目的的工具;同一潜客存在两个活跃Agent;转移目标指向对方Agent内部的特定status。

Law 2 or Law 3?

选定律2还是定律3?

Same goal, same persona, same tool set, same cadence — only more known about the lead → status. Different goal, prompt, tools, channels, or contact intensity → new agent behind a boundary status. If two candidate agents would share ~80% of prompt, tools, and schedule, collapse them into one agent with more statuses.
目标相同、角色相同、工具集相同、触达节奏相同 — 仅潜客信息更完善 → 使用status。目标、提示词、工具、渠道或触达强度不同 → 在边界status后使用新Agent。如果两个候选Agent的提示词、工具和计划重叠度约80%,则合并为一个带有更多status的Agent。

The primitives

原语

Everything a customer asks for lands on one or more of these:
#PrimitiveTriggerCode?Scope
1Agent config (statuses + intake fields)Lead's message, mid-conversationNoOne lead, in-turn
2Workflow HTTP/MCP toolAgent needs external information or action during its turnNoOne lead, synchronous
3Rules (reminders / host notifications / recontact)Meeting lifecycle, stalenessNoOne lead
4Outbound webhookPlatform event (status change, meeting lifecycle)NoNotify an external system, every occurrence
5Status automationLead reaches a specific statusNoCall one HTTP/MCP tool, exactly once per lead
6Background job
cron
or tag event
NoFiltered cohort, declarative steps
7Cloud functionA
lead.*
/
workflow.*
/
meeting.*
event
JSOne lead per event
8Scheduled functionCron + timezoneJSCohort from a lookup query
9Workflow transferTerminal status with
transfer_config
NoOne lead, agent-to-agent handoff
10Intake API / inbound webhookExternal system pushes a lead inNoLead creation + enrollment
11Cadence config (contact blocks + day config)Outreach scheduling: windows, per-channel intensity, hot contactNoA workflow's entire outbound initiative
12Knowledge-base assignmentAgent needs selected account-owned knowledge at runtimeNoExact per-agent subset, ordered by retrieval priority
13Pre-execution hook (tool with
mode: "on_entry"
)
Lead enters the workflow, before the first agent messageNoOne lead, deterministic, cannot be stage-gated
14Pre-processorInbound lead arrives, before any agent owns itNoOrdered condition rules choosing the entry workflow
客户的所有需求都会对应以下一种或多种原语:
序号原语触发条件是否需要代码作用范围
1Agent配置(statuses + 录入字段)潜客消息、对话中途单个潜客、当前对话轮次
2工作流HTTP/MCP工具Agent在对话轮次中需要外部信息或操作单个潜客、同步执行
3规则(提醒/主机通知/重触达)会议生命周期、潜客停滞单个潜客
4出站webhook平台事件(status变化、会议生命周期)通知外部系统、每次事件触发
5状态自动化潜客到达特定status调用一次HTTP/MCP工具、每个潜客仅执行一次
6后台任务
cron
或标签事件
筛选后的客群、声明式步骤
7云函数
lead.*
/
workflow.*
/
meeting.*
事件
是(JS)每个事件对应单个潜客
8定时函数Cron + 时区是(JS)查询得到的客群
9工作流转移带有
transfer_config
的终端status
单个潜客、Agent间移交
10录入API / 入站webhook外部系统推送潜客潜客创建 + 注册
11触达节奏配置(联系时段 + 日期配置)外呼调度:时间窗口、渠道强度、高优先级触达工作流的整个外呼计划
12知识库分配Agent运行时需要选定的账户自有知识库每个Agent的精确子集、按检索优先级排序
13预执行钩子(
mode: "on_entry"
的工具)
潜客进入工作流、Agent首次消息发送前单个潜客、确定性执行、无法按阶段设置门限
14预处理器入站潜客到达、Agent接管前按顺序执行条件规则选择入口工作流

Decision ladder — config beats code

决策阶梯 — 配置优先于代码

Config is operator-visible, editable in the UI, and cannot crash; code is invisible to operators and yours to maintain forever. Walk the ladder top-down and stop at the first rung that expresses the requirement.
  1. Can native conversation config express it? A status, intake field, prompt rule, or deterministic branch → agent config. "Ask for X and branch on it" is statuses + fields, not code. Laws 1 and 2 have usually already placed most of this rung.
  2. Is it a standard lifecycle nudge? Booking confirmations, pre-meeting reminders, host notifications, stale-lead recontact → rules. Configure and stop.
  3. Can a state change define exactly when it should happen? Prefer deterministic execution over asking the model to choose a tool. Status change → filtered outbound webhook when the receiver can act from the event, or status automation when Nexor must call a configured endpoint once with a custom body. Field/variable or other lead event → trigger cloud function (
    information.collected
    ,
    information.updated
    ,
    lead.updated
    , or the narrowest supported event) guarded to the relevant key/change.
  4. Must the result exist before the agent's first message? → pre-execution hook:
    set_workflow_tool_execution({ mode: "on_entry" })
    . The platform runs the tool the moment the lead enters the workflow, before the agent speaks, with no model decision involved. This is the right shape for enrichment, eligibility lookups, and account context — and for a transfer target that needs data ready on arrival. It cannot be stage-gated (the two modes are mutually exclusive), so use it only when "on entry" really is the moment.
  5. Does the agent genuinely need an external result before it can continue the active turn, with no state event that can run it first? Expose the client endpoint as a workflow HTTP/MCP tool in
    mode: "agent_decides"
    . This is the least reliable rung because the model must select and call it. Keep client-specific logic in the client's system, make the contract narrow, and gate it with
    available_in_statuses
    when valid only after a stage such as
    qualified
    .
  6. Is it "filter leads → condition → action"? → background job with declarative steps and actions. Always set
    max_leads_per_cycle
    and
    cooldown_minutes
    ; dry-run anything that messages humans.
  7. Does asynchronous work need custom logic or an external API the job vocabulary can't express? Trigger grammar routes it: "when a lead …" → cloud function (event, one lead). "every morning / Monday …" → scheduled function (cron, cohort). A "when" that tolerates hours of latency across many leads → prefer the scheduled sweep (its dry run shows the whole cohort first).
  8. Does the lead need a fundamentally different conversation or outreach intensity? Goal, persona, cadence, channel mix, or tool set changes → workflow transfer from a boundary status (Law 3). A qualification agent can fan out through terminal statuses such as
    qualified_now
    and
    qualified_later
    , each with its own
    transfer_config
    ; the targets own the high-intensity sales or low-frequency nurture behavior. If both targets would share 80% of their prompt, tools, and schedule, keep one agent with more statuses.
配置对操作员可见、可在UI中编辑且不会崩溃;代码对操作员不可见且需永久维护。从上到下遍历阶梯,在第一个能满足需求的层级停止。
  1. 原生对话配置能否实现? status、录入字段、提示词规则或确定性分支 → Agent配置。“询问X并根据结果分支”属于status + 字段,而非代码。定律1和定律2通常已覆盖该层级的大部分内容。
  2. 是否为标准生命周期提醒? 预订确认、会前提醒、主机通知、停滞潜客重触达 → 规则。完成配置即可停止。
  3. 能否通过状态变化精确定义执行时机? 优先选择确定性执行而非让模型选择工具。状态变化 → 若接收方可直接响应事件则使用筛选后的出站webhook;若Nexor需调用配置的端点并传递自定义请求体则使用状态自动化。字段/变量或其他潜客事件 → 触发云函数(
    information.collected
    information.updated
    lead.updated
    或最窄范围的支持事件),并限制为相关键/变化。
  4. 结果是否必须在Agent首次消息前生成? → 预执行钩子:
    set_workflow_tool_execution({ mode: "on_entry" })
    。平台在潜客进入工作流的瞬间运行该工具,Agent发言前执行,无需模型决策。这是数据 enrichment、资格校验、账户上下文的正确形式 — 也适用于需要数据就绪的转移目标。它无法按阶段设置门限(两种模式互斥),因此仅当“进入时”确实是正确时机时使用。
  5. Agent是否确实需要外部结果才能继续当前对话轮次,且无可用的状态事件提前触发? 将客户端端点作为工作流HTTP/MCP工具暴露,设置
    mode: "agent_decides"
    。这是最不可靠的层级,因为模型必须选择并调用它。将客户端特定逻辑留在客户端系统中,缩小协议范围,并在仅适用于
    qualified
    等阶段时使用
    available_in_statuses
    设置门限。
  6. 是否为“筛选潜客 → 条件 → 操作”? → 带有声明式步骤和操作的后台任务。始终设置
    max_leads_per_cycle
    cooldown_minutes
    ;任何涉及向用户发送消息的操作都先进行试运行。
  7. 异步工作是否需要自定义逻辑或任务词汇无法表达的外部API? 根据触发语法选择:“当潜客……时” → 云函数(事件驱动、单个潜客)。“每天早上/每周一……” → 定时函数(Cron驱动、客群)。可容忍数小时延迟的“当”场景 → 优先选择定时扫描(试运行可先展示整个客群)。
  8. 潜客是否需要完全不同的对话或触达强度? 目标、角色、触达节奏、渠道组合或工具集变化 → 通过边界status进行工作流转移(定律3)。资格校验Agent可通过
    qualified_now
    qualified_later
    等终端status分流,每个status带有各自的
    transfer_config
    ;目标Agent负责高强度销售或低频率培育行为。若两个目标Agent的提示词、工具和计划重叠度达80%,则保留为一个带有更多status的Agent。

The integration compass

集成指南

When the requirement is integration — moving data between Nexor and another system — direction and cadence pick the primitive. Functions are the fully flexible path: editable JavaScript with
axios
available, so any external API is reachable in both directions.
当需求为集成 — 在Nexor与其他系统间传输数据 — 时,方向和节奏决定原语选择。函数是完全灵活的路径:可编辑的JavaScript,支持
axios
,因此可连接任何外部API,双向均可。

Resolve sync direction before choosing a surface

选择载体前先明确同步方向

Treat “sync this information” as incomplete until the direction is explicit. Determine whether the data is moving into Nexor or out of Nexor before recommending or configuring anything. If the request does not make the direction clear, present those two mutually exclusive choices and wait for the answer; do not guess from the word “sync.”
For data moving into Nexor, classify every incoming key before mapping it:
  • Put lead identity and delivery coordinates in the standard lead columns:
    first_name
    ,
    last_name
    ,
    email
    , and
    phone
    . Update them through the normal lead create/update contract, never through metadata. Metadata does not change the address or number Nexor uses to contact the lead.
  • Put every other reusable customer fact the agent should know in
    lead.metadata
    . Create/upsert with a
    metadata
    object or shallow-merge it with
    PATCH
    /
    PUT /api/public/leads/:id
    ; use
    PATCH /api/public/leads/metadata
    for bulk merges. The complete metadata object is loaded into the next agent execution, so a value written now is available on the next turn/run without copying it into prompt prose.
  • Add a workflow field with
    metadata_key
    only when the same value must pre-fill an intake question or participate in a field-only status gate. Metadata remains the source of inbound context; the field is the structural bridge.
For data moving out of Nexor, choose the outbound trigger from the table below. Metadata may be the source value included in a payload, but writing metadata is not an outbound sync mechanism and sends nothing by itself.
DirectionCadenceUseWhy
Nexor → externalStatus changeOutbound webhook or status automationPlatform state fires it deterministically; no model tool-selection decision
Nexor → externalField/variable or lead eventCloud functionThe event fires deterministically; custom code can inspect the changed key and call any endpoint
Nexor ↔ externalDuring the agent's turn, no usable state triggerWorkflow HTTP/MCP toolUse only when the agent needs the response immediately; the client's endpoint remains the source of truth, but model-selected invocation is less reliable
Nexor → externalBatchScheduled function sweepCohort in
ctx.leads[]
, push out per lead or aggregated
External → NexorPush (they call you)Public leads API / inbound hookUpsert + metadata + enrollment in one request, no code
External → NexorPull (Nexor calls them)Scheduled functionQuery the entire leads object with Supabase-style chained filters,
axios
the external API, then create/edit leads with custom metadata via effects or the public API
Deterministic mechanisms win when they express the timing: rules, webhooks, status automations, and event-triggered cloud functions do not depend on the model remembering or deciding to call a tool. Do not copy a client's round-robin, CRM ownership, pricing, or eligibility logic into a prompt or function when their endpoint already owns it. Use an agent-callable tool only when the active conversation truly requires its response before continuing.
“同步此信息”属于不完整需求,必须先明确方向。在推荐或配置任何内容前,确定数据是传入Nexor还是传出Nexor。若请求未明确方向,呈现这两个互斥选项并等待答复;不要从“同步”一词猜测。
对于传入Nexor的数据,在映射前对每个传入键进行分类:
  • 将潜客身份和联系坐标放入标准潜客列:
    first_name
    last_name
    email
    phone
    。通过常规潜客创建/更新协议更新,绝不能通过metadata。metadata不会改变Nexor用于联系潜客的地址或号码。
  • 将Agent需要了解的所有其他可复用客户事实放入
    lead.metadata
    。通过
    metadata
    对象创建/更新,或使用
    PATCH
    /
    PUT /api/public/leads/:id
    进行浅层合并;批量合并使用
    PATCH /api/public/leads/metadata
    。完整的metadata对象会加载到下一次Agent执行中,因此当前写入的值在下次对话轮次/运行时即可使用,无需复制到提示词中。
  • 仅当同一值必须预先填充录入问题或参与仅基于字段的status门限时,才添加带有
    metadata_key
    的工作流字段。metadata始终是入站上下文的来源;字段是结构桥梁。
对于传出Nexor的数据,从下表选择出站触发方式。metadata可作为负载中的源值,但写入metadata本身不是出站同步机制,不会主动发送任何内容。
方向节奏使用原语原因
Nexor → 外部状态变化出站webhook或状态自动化平台状态确定性触发;无需模型选择工具
Nexor → 外部字段/变量或潜客事件云函数事件确定性触发;自定义代码可检查变化的键并调用任何端点
Nexor ↔ 外部Agent对话轮次中,无可用状态触发工作流HTTP/MCP工具仅当Agent需要立即获取响应时使用;客户端端点始终为数据源,但模型选择调用的可靠性较低
Nexor → 外部批量定时函数扫描客群存储在
ctx.leads[]
,按潜客单独推送或聚合推送
外部 → Nexor推送(对方调用我方)公共潜客API / 入站钩子一次请求完成更新+metadata+注册,无需代码
外部 → Nexor拉取(我方调用对方)定时函数使用Supabase风格链式过滤器查询完整潜客对象,通过
axios
调用外部API,然后通过effects或公共API创建/编辑带有自定义metadata的潜客
当时间可明确表达时,优先选择确定性机制:规则、webhook、状态自动化和事件触发的云函数不依赖模型记忆或决定调用工具。当客户的端点已实现轮询、CRM归属、定价或资格逻辑时,不要将其复制到提示词或函数中。仅当当前对话确实需要响应才能继续时,才使用Agent可调用的工具。

Client-owned capabilities and deterministic execution

客户自有能力与确定性执行

Treat the client's endpoint as the capability and Nexor as the orchestrator:
  1. Identify whether a status, field, variable, lead, meeting, or workflow event defines the moment of execution. If it does, wire that event to a webhook, status automation, or cloud function; do not ask the agent to call the endpoint.
  2. Keep the authoritative business decision in the endpoint. Nexor passes facts; neither the agent nor a function should duplicate the client's algorithm.
  3. Use a conversational HTTP/MCP tool only when the agent must obtain the result inside the active turn and a deterministic trigger cannot run it first.
  4. For remaining agent-callable tools, set
    available_in_statuses
    to the exact valid status keys. Pair a
    qualified
    gate with
    requires_all_fields
    /
    required_field_keys
    so availability and booking cannot run before qualification.
  5. Use
    call_once
    for irreversible conversational operations that must run once per workflow run; leave it off read-only tools that may need a legitimate refresh.
  6. Define success, failure, persistence, and retry behavior. Never let the agent invent an assignment, slot, price, or external result after a failed call.
Read the workflow-tool and stage-gate contract in references/configuration-reference.md and use the round-robin mapping in references/recipes.md when the ask resembles sales-rep assignment.
将客户端点视为能力载体,Nexor作为编排器:
  1. 确定执行时刻是否由status、字段、变量、潜客、会议或工作流事件定义。若是,将该事件与webhook、状态自动化或云函数关联;不要让Agent调用端点。
  2. 将权威业务决策留在端点中。Nexor仅传递事实;Agent或函数不应复制客户的算法。
  3. 仅当Agent必须在当前对话轮次中获取结果且确定性触发无法提前执行时,才使用对话式HTTP/MCP工具。
  4. 对于剩余的Agent可调用工具,设置
    available_in_statuses
    为精确的有效status键。将
    qualified
    门限与
    requires_all_fields
    /
    required_field_keys
    搭配,确保工具在资格校验完成前无法使用。
  5. 对于每个工作流运行中必须仅执行一次的不可逆对话操作,设置
    call_once
    ;对于可能需要合法刷新的只读工具,关闭该设置。
  6. 定义成功、失败、持久化和重试行为。调用失败后,绝不能让Agent自行生成分配、时段、价格或外部结果。
阅读references/configuration-reference.md中的工作流工具和阶段门限协议,当需求类似销售代表分配时,使用references/recipes.md中的轮询映射。

Workflow

工作流程

  1. Restate the ask as trigger → condition → action, resolve sync direction as into Nexor / out of Nexor before choosing a surface, classify its timing as in-turn / event / batch / inbound, and separate what the agent must ask (intake fields), what the customer's systems send (standard lead identity columns versus metadata), and what must happen (tool call or automation).
  2. Apply the three laws to draft the skeleton before choosing any primitive: list every fact the design needs as a named variable with its store and its readers (Law 1); list every in-agent stage as a status key with its entry criterion and gate (Law 2); list every identity switch as a boundary status with its shape, target agent, and — for a pause boundary — its executor (Law 3). Anything you cannot place in one of those three lists is not designed yet; place it before continuing.
  3. Call
    describe_agent_configuration
    before proposing any non-trivial or multi-agent build, and read current state with
    list_workflows
    /
    get_workflow
    /
    list_workflow_tools
    /
    list_webhooks
    . The platform ships its own required process and surface map; follow it rather than a remembered one.
  4. Walk the ladder. Note every rung you skip and why — that reasoning is part of the deliverable.
  5. Prefer a deterministic state trigger. For a status change choose webhook/status automation first; for a field/variable or other lead event choose a cloud function. Use an in-turn tool only when the agent must receive the result before continuing, then gate it to the statuses where it is valid.
  6. Read references/recipes.md and start from the closest worked mapping; read references/configuration-reference.md to fill in exact field names and values for the chosen primitives; read references/mcp-tool-surface.md before the first write.
  7. Before asking the customer about timezone or channels, call
    inspectAccountChannels
    (or, outside the Master Editor,
    get_account_readiness
    plus
    list_whatsapp_numbers
    ,
    list_email_senders
    , and
    list_phone_numbers
    ). Treat SMS as the active phone-number rows with
    sms_enabled: true
    . Account facts are evidence, not clarification prompts: never ask whether the customer already has a WhatsApp number, email sender, call number, SMS channel, or saved timezone.
  8. Write an expected channel manifest for every agent: enabled channel plus the exact selected resource id for WhatsApp, email, call, and SMS. Include each resource's current owner. Email senders are shareable; a WhatsApp number has one direct owner, a call number has one
    workflow_id
    , and an SMS route has one
    sms_workflow_id
    . Call and SMS may legitimately route the same physical number to different agents. Reject or resolve duplicate exclusive claims across the whole plan before mutation. If exactly one usable resource exists for a requested channel, offer that observed resource versus configuring a new one. If several exist, show every observed resource in a finite selector plus the new-resource path. If none exist, say so and offer setup versus continuing without the channel. Never turn these finite choices into open-text questions.
  9. Preflight the whole system with
    review_agent_system_plan({ plan })
    before mutating anything
    , expressing handoffs as
    transfer_to_agent_ref
    between plan-local agent refs. Resolve every
    blocking_issue
    and
    clarification_question
    until
    ready_for_signoff
    is true, then show the returned summary and ask the exact
    signoff_prompt
    question. Do not call any create/update/run tool until the user approves the
    plan_fingerprint
    .
  10. Mutate in dependency order so nothing references an id or key that does not exist yet:
    create_workflow
    (the complete funnel — statuses carry their full stage config including gates, hints, timeouts and flags, plus the complete fields array; most field properties cannot be added later) → check the returned
    pipeline_reconciliation
    report and resolve every leftover seeded status, missing key, and warning before the next step → workflow tools →
    update_workflow_config
    for status automations → webhooks and rules → channel bindings → transfers (
    update_workflow_status
    with
    transfer_config
    once targets have real ids) → knowledge-base attachments. Agents are created paused; keep them paused through the whole build. See references/mcp-tool-surface.md for the exact tool per step and what each write overwrites.
  11. For every agent build, inventory the account catalog with
    list_knowledge_bases
    without
    workflow_id
    , then write an expected knowledge manifest: one row per agent with the exact account-owned KB ids/names it should use and their retrieval order. Account ownership is availability, not assignment. Infer relevance only when the KB description and agent responsibility make it unambiguous; otherwise resolve the choice before mutating. Never attach every account KB by default unless the operator explicitly wants every agent to use all of them.
  12. For a multi-agent design, write an expected connection manifest before mutating anything: one row per handoff with
    source_agent_ref
    ,
    source_status_key
    ,
    boundary_shape
    (terminal transfer or pause + executor), and
    target_agent_ref
    . Keep this manifest independent of creation order.
  13. After every involved agent has a real id, reconcile all three manifests. For channels, write selected real ids (
    config.email_sender_id
    ,
    assign_whatsapp_to_workflow
    ,
    assign_number_to_workflow
    , and
    set_number_sms
    ), synchronize
    config.disabled_channels
    , ensure
    first_contact_channel
    still names an enabled usable channel, and re-run the inventory. Never silently steal a number already assigned to another agent: approval must name the resource, capability, old owner, new owner, and routing impact. Include every displaced agent in read-back and either disable its lost capability or apply its separately confirmed replacement. For transfers, update each source status with the destination's real id, including returning to an earlier-created source after a later target is created. For knowledge, attach missing expected KBs and detach unexpected KBs from each agent without deleting the client-owned KB. Read every involved agent, its channel inventory, and its attached KB list back. Repair and re-read until there are zero missing, unresolved, misdirected, or extra channels, connections, and assignments. Do not finalize, report success, or activate while any manifest is incomplete.
  14. Produce the configuration spec (see Output).
  15. State the verification path: which previews/dry runs, channel/connection/KB read-backs, and blocked/allowed tool tests to perform, and what they must show, before anything is activated.
  1. 将需求重述为触发条件 → 条件 → 操作,在选择载体前明确同步方向为传入Nexor / 传出Nexor,将时间分类为对话轮次内 / 事件驱动 / 批量 / 入站,区分Agent必须询问的内容(录入字段)、客户系统必须发送的内容(标准潜客身份列vs metadata)以及必须执行的操作(工具调用或自动化)。
  2. 在选择任何原语前应用三定律草拟框架:列出设计所需的每一个事实,作为带有存储位置和读取方的命名变量(定律1);列出每个Agent内的阶段,作为带有进入条件和门限的status键(定律2);列出每一次身份切换,作为带有形式、目标Agent以及执行者(针对暂停边界)的边界status(定律3)。任何无法归入这三类的内容都尚未完成设计,需先处理后再继续。
  3. 在提出任何非 trivial 或多Agent构建方案前调用
    describe_agent_configuration
    ,并通过
    list_workflows
    /
    get_workflow
    /
    list_workflow_tools
    /
    list_webhooks
    读取当前状态。平台自带要求的流程和界面映射;遵循该映射而非记忆中的内容。
  4. 遍历决策阶梯。记录跳过的每个层级及原因 — 该推理过程是交付成果的一部分。
  5. 优先选择确定性状态触发。对于状态变化,优先选择webhook/状态自动化;对于字段/变量或其他潜客事件,选择云函数。仅当Agent必须提前获取结果才能继续时使用对话轮次内工具,然后将其限制在有效status中。
  6. 阅读references/recipes.md,从最接近的已实现映射开始;阅读references/configuration-reference.md填充所选原语的精确字段名和值;首次写入前阅读references/mcp-tool-surface.md
  7. 在询问客户时区或渠道前,调用
    inspectAccountChannels
    (或在Master Editor外,调用
    get_account_readiness
    加上
    list_whatsapp_numbers
    list_email_senders
    list_phone_numbers
    )。将
    sms_enabled: true
    的活跃电话号码行视为SMS渠道。账户事实是证据,而非澄清问题:绝不要询问客户是否已有WhatsApp号码、邮件发送者、呼叫号码、SMS渠道或保存的时区。
  8. 为每个Agent编写预期渠道清单:启用的渠道加上WhatsApp、邮件、呼叫和SMS的精确选定资源ID。包含每个资源的当前所有者。邮件发送者可共享;一个WhatsApp号码有一个直接所有者,一个呼叫号码有一个
    workflow_id
    ,一个SMS路由有一个
    sms_workflow_id
    。呼叫和SMS可合法地将同一物理号码路由到不同Agent。在修改前拒绝或解决整个方案中的重复排他性声明。若请求的渠道恰好有一个可用资源,提供该已观测资源或配置新资源的选项。若存在多个资源,展示所有已观测资源的有限选择器加上新资源路径。若没有可用资源,告知客户并提供设置或不使用该渠道的选项。绝不要将这些有限选择转化为开放式文本问题。
  9. 在修改任何内容前,使用
    review_agent_system_plan({ plan })
    对整个系统进行预检
    ,将移交表示为计划内Agent引用之间的
    transfer_to_agent_ref
    。解决所有
    blocking_issue
    clarification_question
    ,直到
    ready_for_signoff
    为true,然后返回的摘要并询问确切的
    signoff_prompt
    问题。在用户批准
    plan_fingerprint
    前,不要调用任何创建/更新/运行工具。
  10. 按依赖顺序修改,确保没有引用不存在的ID或键:
    create_workflow
    完整漏斗 — status包含完整的阶段配置,包括门限、提示、超时和标志,加上完整字段数组;大多数字段属性无法后续添加) → 检查返回的
    pipeline_reconciliation
    报告,解决所有遗留的种子status、缺失键和警告后再进行下一步 → 工作流工具 →
    update_workflow_config
    配置状态自动化 → webhook和规则 → 渠道绑定 → 转移(目标拥有真实ID后,通过
    update_workflow_status
    设置
    transfer_config
    ) → 知识库附件。Agent创建时处于暂停状态;在整个构建过程中保持暂停。查看references/mcp-tool-surface.md获取每个步骤的精确工具及写入内容的覆盖范围。
  11. 对于每个Agent构建,使用
    list_knowledge_bases
    workflow_id
    )盘点账户目录,然后编写预期知识库清单:每个Agent一行,包含其应使用的精确账户自有KB ID/名称及检索顺序。账户所有权表示可用性,而非分配。仅当KB描述和Agent职责明确相关时推断相关性;否则在修改前解决选择问题。除非操作员明确要求每个Agent使用所有KB,否则绝不要默认附加所有账户KB。
  12. 对于多Agent设计,在修改前编写预期连接清单:每个移交一行,包含
    source_agent_ref
    source_status_key
    boundary_shape
    (终端转移或暂停+执行者)和
    target_agent_ref
    。保持该清单独立于创建顺序。
  13. 在所有涉及的Agent拥有真实ID后,协调所有三个清单。对于渠道,写入选定的真实ID(
    config.email_sender_id
    assign_whatsapp_to_workflow
    assign_number_to_workflow
    set_number_sms
    ),同步
    config.disabled_channels
    ,确保
    first_contact_channel
    仍指向启用的可用渠道,并重新运行盘点。绝不要静默占用已分配给其他Agent的号码:批准必须明确资源、能力、旧所有者、新所有者和路由影响。在回读中包含所有受影响的Agent,并禁用其丢失的能力或应用单独确认的替代方案。对于转移,使用目标的真实ID更新每个源status,包括在创建较晚的目标后返回更新较早创建的源。对于知识库,为每个Agent附加缺失的预期KB并移除意外的KB,无需删除客户自有KB。回读所有涉及的Agent、其渠道清单和附加的KB列表。修复并重新回读,直到渠道、连接和分配没有遗漏、未解决、错误指向或多余项。任何清单不完整时,不要完成、报告成功或激活。
  14. 生成配置规范(见输出部分)。
  15. 说明验证路径:激活前需执行的预览/试运行、渠道/连接/KB回读、工具阻塞/允许测试,以及这些操作必须显示的结果。

Facts that decide designs

影响设计的关键事实

These are the semantics customers (and naive designs) most often get wrong:
  • create_workflow
    's statuses are the entire funnel — the backend seeds defaults, and seeded stages must not survive.
    The create endpoint seeds a default pipeline (New, Contacted, In conversation, system stages) and appends your statuses to it; the MCP tool reconciles this automatically and returns a
    pipeline_reconciliation
    report. The funnel is correct only when
    unrequested_statuses_remaining
    ,
    missing_requested_statuses
    , and
    warnings
    are all empty — resolve leftovers with
    get_pipeline_impact
    +
    delete_workflow_status
    and missing keys with
    update_workflow_structure
    before configuring anything that references a status. A seeded stage left in place is invisible to your design's gates, hints, and transfers, and duplicates (e.g. a stray
    payment_sent
    next to your
    send_link
    ) mis-route leads into dead stages.
  • The agent routes on
    entry_hint
    , not
    description
    .
    A status's
    description
    never reaches the prompt. The placement rule ("annual income is under 800,000 — place the lead here") goes in
    entry_hint
    ; gate advancement with
    variable_refs
    /
    required_field_keys
    . When the branch is fully determined by saved field values, encode it as
    transition_rules.rule_groups
    (server-evaluated
    field
    /
    operator
    /
    value
    conditions) with
    auto_evaluate: true
    , so the platform routes the lead the moment the fields are saved instead of depending on the agent calling
    set_lead_status
    .
  • is_qualified
    marks; gates enforce.
    The qualification stage type is a reporting/UI flag. The server-side gate is
    required_field_keys
    (takes precedence) /
    requires_all_fields
    plus
    transition_rules.rule_groups
    — and gates only block entry into non-terminal statuses and
    won
    -category terminals; entry into
    lost
    /transfer terminals is guided by
    entry_hint
    , not blocked.
  • Channel hours are one flag, not per-channel. Calls are always gated to the cadence windows (hard-coded, never 24/7); WhatsApp/email/SMS run 24/7 unless
    config.gate_outbound_to_hours: true
    gates them all together. Inbound replies bypass scheduling entirely. No weekly frequency cap exists for any channel — express "at most N per week" with per-block intensity,
    disabled_channels
    , or a background job with
    cooldown_minutes
    , and say which approximation you chose.
  • Discard rules are statuses, not automations — and
    lost
    stops initiating, not responding.
    "If the lead doesn't qualify, stop contacting them" is a terminal
    category: "lost"
    status whose
    entry_hint
    and
    transition_rules
    carry the rule, configured visibly in the agent and processed during the conversation. Entering it halts all proactive outbound and the run cannot be reactivated — but the agent still replies briefly if the lead writes in (built-in lost-lead behavior: no selling, no booking offers).
    pause_bot
    is the only control that fully silences replies;
    futurology_queue
    defers for recontact; only a terminal
    lost
    status discards.
  • Metadata is the default custom-context path, not the intake config. Whenever a customer asks how to give the agent arbitrary information about a lead, offer the lead's
    metadata
    JSON object first. Its values may use any JSON shape and the complete object reaches the runtime prompt.
    workflow_fields
    defines only what the agent asks for, validates, or uses to gate status advancement; bridge the specific inbound key with
    metadata_key
    only for those needs (one direction: metadata → field prefill). Metadata updates shallow-merge top-level keys, so resend a complete nested object when changing only part of it.
  • “Sync” has a direction before it has a primitive. Establish whether information is entering or leaving Nexor. For inbound data, map
    first_name
    ,
    last_name
    ,
    email
    , and
    phone
    to standard lead columns and put other agent-readable facts in metadata; those metadata values become available on the next agent execution. For outbound data, use an outbound trigger—metadata writes do not transmit anything.
  • Deterministic triggers beat model-selected tools. If "when" can be expressed as a status, field, variable, lead, meeting, or workflow event, let the platform fire the integration. Tool descriptions and prompt instructions can still be hallucinated or skipped; event subscriptions and triggers do not depend on model choice.
  • Tool descriptions guide; stage gates enforce. Put invocation guidance in the tool description and prompt, but use
    workflow_tools.available_in_statuses
    to block execution outside valid statuses.
    null
    / an empty list means unrestricted. Pair the gate with required fields on the qualifying status; changing to that status can unlock the tool within the same turn.
  • Custom logic belongs behind the endpoint. If HubSpot or a client service already performs round robin, territory routing, eligibility, or pricing, a deterministic trigger should call it whenever possible; an agent tool calls it only when the response is needed in-turn. Nexor should not maintain a second copy of that logic.
  • "Notify me" has two shapes. A webhook subscription filtered on
    to_status.key
    fires on every matching status change (your endpoint dedupes); a status automation fires exactly once per lead per rule and can template the request body from lead data.
  • Transfers fire only from hard-terminal statuses.
    is_terminal
    is checked before
    transfer_config
    is even read, and soft-terminal keys (
    future_*
    ,
    contact_later
    ,
    colder
    ) are filtered out first — either mistake saves cleanly and never fires. Auto-transfer is also skipped while the lead is in human support (
    in_support
    ). Transfers always create a fresh run on the target agent at its initial status — a transfer cannot land on a chosen status in another agent (the only status→status pointer is
    timeout_config.target_status_key
    , same workflow only). Source cadence is cancelled, the target's cadence starts over, and collected fields travel as a read-only transfer-chain snapshot — they are not copied into the target's fields. If the "transfer" is just a stage of the same conversation, it's a status, not a transfer.
  • Agent creation order never satisfies a connection. A handoff exists only after the source's terminal status has been read back with
    transfer_config.target_workflow_id
    equal to the destination's real id. Preserve the expected connection manifest across the build, wait until all referenced ids exist, then reconcile every source. Creating A before B means returning to A after B exists; creating B before A changes nothing. A multi-agent build is incomplete until every expected edge passes this read-back check.
  • Account knowledge is not agent knowledge.
    knowledge_bases
    is the client-owned catalog;
    workflow_knowledge_bases
    is the per-agent assignment. One KB may be shared by several agents, and each agent may receive a different ordered subset. Listing the account catalog proves only that a KB exists. Agent access exists only after
    list_knowledge_bases({ workflow_id })
    reads that KB back on the intended agent. Create or reuse the account KB first, attach by its real id, detach only the relationship when removing access, and never delete shared content to change one agent's assignment.
  • Account channels are not questions. The account already knows its saved timezone, connected WhatsApp numbers, send-capable email senders, active call numbers, and which active numbers currently have SMS enabled. Read them before planning. One resource means “use this exact resource or configure another”; several means a real resource selector; zero means an explicit setup/omit decision. Never ask “do you already have a WhatsApp number?” or request an email/phone the platform can list.
    verification_status: "verified"
    is not enough when email
    can_send
    is explicitly false, and
    sms_enabled: false
    means the row is not a current SMS channel—not proof that it can safely be enabled.
  • The source selects intensity; the target implements it. Put mutually exclusive routing criteria in source
    entry_hint
    values and one
    transfer_config
    on each terminal branch. Put sales urgency, booking tools, nurture tone, enabled channels, and contact frequency on the corresponding target workflows — never on the source status.
  • Function effects are buffered and return nothing, so a scheduled function cannot create a lead and enroll it in the same run. To sync leads in and start conversations, call the public leads API (it upserts, merges metadata, enrolls, and starts first contact in one request) from the function, or use a two-phase sweep.
  • Send-once is stateful, never assumed. Cohort messaging without
    then_status_key
    (or a cooldown) re-sends every cycle.
  • A tool can run without the model choosing to.
    set_workflow_tool_execution({ mode: "on_entry" })
    makes a tool a pre-execution hook that fires when the lead enters the workflow, before the first agent message.
    on_entry
    and
    agent_decides
    are mutually exclusive, and an on-entry hook cannot be stage-gated — the call is rejected if you pass
    available_in_statuses
    . Before proposing a conversational tool, ask whether "on entry" is actually the moment; if it is, the model never gets a chance to skip it.
  • Status automations have no tool of their own. They live in the workflow
    config
    bag and are written with
    update_workflow_config({ config: { status_automations: [...] } })
    . The bag merges at the top level but the array is replaced wholesale, so read
    get_workflow
    and send the complete array every time. Rules fire on
    on_status_key
    for
    enabled !== false
    , exactly once per (workflow, lead, rule key) forever via a ledger, with one automatic retry. A missing
    args_template
    value aborts the rule instead of sending a partial body — which is why the value must be in metadata before the lead can arrive.
  • Three unrelated things are called "paused."
    workflows.is_paused
    (the agent is off — every new agent starts here),
    workflow_runs.is_paused
    (one lead's run, set by
    stop_automation
    , and what job
    exclusions.skip_paused
    filters on), and status
    pause_bot
    (the agent goes quiet while the lead sits there). They do not imply each other.
  • The platform validates your plan before you build it.
    review_agent_system_plan
    blocks on undefined transfer targets, duplicate refs, and missing goals, and raises clarifications for missing responsibility, language, timezone, channels, or a status with no entry criterion. It returns a
    plan_fingerprint
    and the exact sign-off question. Treat a clean review plus explicit user approval as the precondition for the first mutation, not a formality.
这些是客户(及不成熟设计)最常误解的语义:
  • create_workflow
    的status是完整漏斗 — 后端会生成默认值,且种子阶段必须删除。
    创建端点会生成默认流程(New、Contacted、In conversation、系统阶段)并将你的status追加到后面;MCP工具会自动协调并返回
    pipeline_reconciliation
    报告。仅当
    unrequested_statuses_remaining
    missing_requested_statuses
    warnings
    均为空时,漏斗才正确 — 在配置任何引用status的内容前,使用
    get_pipeline_impact
    +
    delete_workflow_status
    解决遗留项,使用
    update_workflow_structure
    添加缺失的键。保留的种子阶段对设计的门限、提示和转移不可见,重复项(例如,你的
    send_link
    旁边存在多余的
    payment_sent
    )会将潜客路由到无效阶段。
  • Agent根据
    entry_hint
    路由,而非
    description
    status的
    description
    永远不会传入提示词。分支规则(“年收入低于800,000 — 将潜客放入此阶段”)放入
    entry_hint
    ;使用
    variable_refs
    /
    required_field_keys
    设置门限推进流转。当分支完全由保存的字段值决定时,将其编码为
    transition_rules.rule_groups
    (服务器评估的
    field
    /
    operator
    /
    value
    条件)并设置
    auto_evaluate: true
    ,使平台在字段保存后立即路由潜客,而非依赖Agent调用
    set_lead_status
  • is_qualified
    是标记;门限才是强制约束。
    资格阶段类型是报告/UI标志。服务器端门限是
    required_field_keys
    (优先级更高) /
    requires_all_fields
    加上
    transition_rules.rule_groups
    — 门限仅阻止进入非终端status和
    won
    类终端;进入
    lost
    /转移终端由
    entry_hint
    引导,不受阻塞。
  • 渠道时间是单个标志,而非每个渠道单独设置。 呼叫始终受触达节奏窗口限制(硬编码,绝非24/7);WhatsApp/邮件/SMS默认24/7运行,除非
    config.gate_outbound_to_hours: true
    将它们全部限制在窗口内。入站回复完全绕过调度。任何渠道都没有每周频率上限 — 使用时段强度、
    disabled_channels
    或带有
    cooldown_minutes
    的后台任务表达“每周最多N次”,并说明你选择的近似方式。
  • 丢弃规则是status,而非自动化 — 且
    lost
    停止主动触达,而非停止响应。
    “若潜客不合格,停止联系他们”是终端
    category: "lost"
    status,其
    entry_hint
    transition_rules
    包含规则,在Agent中可见配置并在对话中处理。进入该status会停止所有主动外呼,且运行无法重新激活 — 但如果潜客发起消息,Agent仍会简短回复(内置流失潜客行为:不推销、不提供预订)。
    pause_bot
    是唯一能完全停止回复的控制;
    futurology_queue
    延迟重触达;只有终端
    lost
    status会丢弃潜客。
  • Metadata是默认自定义上下文路径,而非录入配置。 每当客户询问如何向Agent提供潜客的任意信息时,首先推荐潜客的
    metadata
    JSON对象。其值可使用任何JSON格式,完整对象会传入运行时提示词。
    workflow_fields
    仅定义Agent询问、验证或用于设置status门限的内容;仅当需要时(单向:metadata → 字段预填充)使用
    metadata_key
    连接特定入站键。metadata更新会浅层合并顶层键,因此仅修改嵌套对象的部分内容时需重新发送完整嵌套对象。
  • “同步”在选择原语前必须明确方向。 确定信息是传入还是传出Nexor。对于入站数据,将
    first_name
    last_name
    email
    phone
    映射到标准潜客列,将其他Agent可读事实放入metadata;这些metadata值会在下次Agent执行时可用。对于出站数据,使用出站触发 — 写入metadata不会传输任何内容。
  • 确定性触发优于模型选择的工具。 若“何时”可表示为status、字段、变量、潜客、会议或工作流事件,让平台触发集成。工具描述和提示词指令仍可能被幻觉或跳过;事件订阅和触发不依赖模型选择。
  • 工具描述起引导作用;阶段门限起强制作用。 将调用指导放入工具描述和提示词,但使用
    workflow_tools.available_in_statuses
    阻止在无效status中执行。
    null
    / 空列表表示无限制。将门限与资格status的必填字段搭配;切换到该status可在同一对话轮次内解锁工具。
  • 自定义逻辑应放在端点后。 如果HubSpot或客户服务已实现轮询、区域路由、资格或定价,应尽可能使用确定性触发调用;仅当响应需要在对话轮次内获取时才使用Agent工具。Nexor不应维护该逻辑的副本。
  • “通知我”有两种形式。 基于
    to_status.key
    筛选的webhook订阅会在每次匹配的status变化时触发(你的端点需去重);状态自动化每个潜客每个规则仅触发一次,并可从潜客数据模板化请求体。
  • 转移仅从硬终端status触发。 在读取
    transfer_config
    前会先检查
    is_terminal
    ,且软终端键(
    future_*
    contact_later
    colder
    )会被优先过滤 — 任何一种错误都会导致配置成功保存但永远不会触发。当潜客处于人工支持(
    in_support
    )时,自动转移也会被跳过。转移始终在目标Agent上创建新运行从其初始status开始 — 转移无法直接到达对方Agent的指定status(唯一的status→status指针是
    timeout_config.target_status_key
    ,仅适用于同一工作流)。源触达节奏会被取消,目标触达节奏重新启动,收集的字段作为只读转移链快照传递 — 不会复制到目标的字段中。如果“转移”只是同一对话的一个阶段,那它是status,而非转移。
  • Agent创建顺序无法满足连接需求。 只有当源终端status的
    transfer_config.target_workflow_id
    等于目标的真实ID时,移交才存在。在构建过程中保留预期连接清单,等待所有引用的ID存在,然后协调每个源。先创建A再创建B意味着在B创建后返回更新A;先创建B再创建A无影响。多Agent构建在所有预期连接通过回读检查前视为未完成。
  • 账户知识库不等于Agent知识库。
    knowledge_bases
    是客户自有目录;
    workflow_knowledge_bases
    是每个Agent的分配。一个KB可被多个Agent共享,每个Agent可接收不同的有序子集。列出账户目录仅证明KB存在。只有当
    list_knowledge_bases({ workflow_id })
    在目标Agent上回读到该KB时,Agent访问权限才存在。先创建或复用账户KB,通过真实ID附加,移除访问权限时仅解除关系,绝不要删除共享内容来修改单个Agent的分配。
  • 账户渠道不是问题。 账户已知道其保存的时区、连接的WhatsApp号码、可发送的邮件发送者、活跃呼叫号码以及哪些活跃号码当前启用了SMS。规划前先读取这些信息。一个资源意味着“使用此精确资源或配置其他资源”;多个资源意味着真实资源选择器;零个资源意味着明确的设置/省略决策。绝不要问“你已有WhatsApp号码吗?”或请求平台可列出的邮件/电话。当邮件
    can_send
    明确为false时,
    verification_status: "verified"
    不足够;
    sms_enabled: false
    表示该行不是当前SMS渠道 — 不证明可安全启用。
  • 源选择强度;目标实现强度。 将互斥路由标准放入源的
    entry_hint
    值,并在每个终端分支设置一个
    transfer_config
    。将销售紧迫性、预订工具、培育语气、启用渠道和联系频率放在对应的目标工作流中 — 绝不要放在源status中。
  • 函数效果是缓冲的且无返回值,因此定时函数无法在同一运行中创建潜客并注册。要同步潜客启动对话,从函数调用公共潜客API(一次请求完成更新、合并metadata、注册和首次触达),或使用两阶段扫描。
  • 仅发送一次是有状态的,绝不能假设。 没有
    then_status_key
    (或冷却时间)的客群消息会在每个周期重新发送。
  • 工具可无需模型选择即可运行。
    set_workflow_tool_execution({ mode: "on_entry" })
    使工具成为预执行钩子,在潜客进入工作流时触发,Agent首次消息发送前执行。
    on_entry
    agent_decides
    互斥,且入站钩子无法按阶段设置门限 — 若传递
    available_in_statuses
    ,调用会被拒绝。在提出对话式工具前,先询问“进入时”是否确实是正确时机;若是,模型永远不会有机会跳过它。
  • 状态自动化没有自有工具。 它们存在于工作流
    config
    包中,通过
    update_workflow_config({ config: { status_automations: [...] } })
    写入。包在顶层合并,但数组会被完全替换,因此每次发送前需读取
    get_workflow
    并发送完整数组。规则在
    on_status_key
    触发,
    enabled !== false
    时启用,通过台账确保每个(工作流、潜客、规则键)永远仅执行一次,带有一次自动重试。缺失的
    args_template
    值会中止规则而非发送部分请求体 — 这就是为什么值必须在潜客到达前放入metadata。
  • 三个无关事物都被称为“暂停”。
    workflows.is_paused
    (Agent关闭 — 每个新Agent初始状态)、
    workflow_runs.is_paused
    (单个潜客的运行,由
    stop_automation
    设置,任务
    exclusions.skip_paused
    过滤的对象)和status的
    pause_bot
    (Agent静默,潜客处于该状态)。它们互不影响。
  • 平台在构建前验证你的方案。
    review_agent_system_plan
    会阻止未定义的转移目标、重复引用和缺失目标,并对缺失职责、语言、时区、渠道或无进入条件的status提出澄清。它返回
    plan_fingerprint
    和确切的签字确认问题。将通过审核加上用户明确批准作为首次修改的前提,而非形式。

Guardrails

防护规则

  • Never mutate before
    review_agent_system_plan
    returns
    ready_for_signoff: true
    and the user approves the returned
    plan_fingerprint
    . Agents are created paused; keep them paused until read-back passes and activation is confirmed separately.
  • Never attempt to delete an agent or workflow. Agent/workflow deletion is not available through the Nexor MCP surface: do not call, suggest, or invent
    delete_workflow
    ,
    delete_agent
    , or any equivalent workflow/agent deletion operation. If a customer asks to remove one, state that this action is unavailable to the agent and leave it for an authorized human in the supported product surface; do not substitute pausing, archiving, or another mutation without separate explicit approval.
  • Know what each write destroys before sending it.
    set_workflow_prompt
    overwrites the whole prompt,
    update_workflow_config
    replaces any array you touch,
    set_workflow_cadence
    is a whole-document PUT for blocks, and
    update_workflow_config({ replace: true })
    wipes the config bag. Read the current value first — see references/mcp-tool-surface.md.
  • Know what each write accepts before sending it.
    update_workflow
    mutates
    name
    ,
    description
    ,
    goal_statement
    , the agent identity (
    language
    ,
    timezone
    ,
    region_style
    ,
    agent_name
    ,
    agent_role
    ,
    company_name
    ,
    begin_message
    ), and
    master_workflow_id
    ; every call must carry at least one of them or it fails
    INVALID_INPUT
    . Pause state goes through
    set_workflow_active
    and the channel mix through channel-binding tools plus
    config.disabled_channels
    — neither is an
    update_workflow
    parameter. Persona and business rules are prompt text:
    set_workflow_prompt
    /
    set_channel_prompt
    , never identity fields.
  • Reject any design that breaks a law and fix its shape rather than compensating with prompt wording. Name the violated law: a needed fact carried only in prompt prose or conversation history (Law 1); a stage change with no status key (Law 2); a tone, persona, or tool-set switch that is not a boundary status with a named target agent (Law 3). Prompt text is speech; fields, statuses, and transfers are structure — only structure is enforced.
  • A pause boundary with no named executor is an unfinished transfer. Either make the boundary terminal with
    transfer_config
    , or state the job/API/human that performs the handoff and verify it moves a test lead.
  • Never make a fact reachable in only one store when both a gate and an automation need it. If a status gates on
    field_x
    and an
    args_template
    must send it, the value must exist as a field and in metadata before the lead reaches that status.
  • Dry-run first for anything that messages humans or mutates many leads, and read the candidate list before activating. Manual function runs preview effects without applying them — but outbound HTTP in a dry run is real; point test runs at test endpoints.
  • Get explicit customer confirmation before activating any cohort automation or anything that sends messages.
  • Make side-effecting tools idempotent and return a persistent external operation ID. Set
    call_once
    where a second successful call would be wrong, and define what the agent says when the endpoint times out or fails.
  • For every proposed agent tool, state why a webhook, status automation, or event cloud function cannot provide the same behavior. If no immediate conversational dependency exists, replace the tool with the deterministic mechanism.
  • Test every stage-gated tool twice: a call before the allowed status must return
    tool_not_available_in_stage
    , and the same valid call after qualification must reach the endpoint. Do not rely on prompt wording as the gate.
  • Do not design on unsupported surface: API-triggered background jobs,
    workflow_scoped
    filter mode, and CRM-event job triggers (other than tag and payment events) are not currently functional — see the reference for the supported list.
  • Never place credentials in function code or tool config; store them as Environment Variables and reference
    env.KEY
    /
    {{env.KEY}}
    .
  • If the requirement genuinely fits no primitive, say exactly what is missing instead of forcing an approximation.
  • Treat multi-agent finalization as graph closure, not agent-count completion. If any expected transfer is missing, unresolved, attached to the wrong source status, or points to the wrong target id, report the build as incomplete and continue reconciliation or surface the exact failed edge. Never emit a success claim for a partially connected system.
  • Treat knowledge configuration as assignment closure. Compare each agent's observed KB ids and priority order with its expected manifest; attach missing links and detach extra links, then read back again. Never infer access from the account catalog, and never claim an agent is fully configured while its KB set differs from the plan.
  • Treat channel configuration as assignment closure. Compare every requested channel and selected resource id with the post-build account inventory and workflow config. Never infer a binding from “channel enabled,” never reassign an already-bound number without targeted confirmation, and re-read the exclusive owner immediately before the write so stale approval cannot move a resource from a different incumbent. Never claim completion while a selected sender/number is missing, unusable, bound to the wrong agent, disabled by config, or contradicted by
    first_contact_channel
    . If WhatsApp will initiate outreach, list an
    APPROVED
    greeting/opening/legacy_greeting/outbound template, configure it with
    set_opening_templates
    , and read it back with
    get_template_pool
    before activation.
  • review_agent_system_plan
    返回
    ready_for_signoff: true
    用户批准返回的
    plan_fingerprint
    前,绝不要修改配置。Agent创建时处于暂停状态;在回读通过且单独确认激活前保持暂停。
  • 绝不要尝试删除Agent或工作流。 Agent/工作流删除无法通过Nexor MCP界面完成:不要调用、建议或虚构
    delete_workflow
    delete_agent
    或任何等效的工作流/Agent删除操作。若客户要求移除,说明该操作对Agent不可用,留给授权人员在支持的产品界面中处理;未经单独明确批准,不要用暂停、归档或其他修改替代。
  • 在发送前了解每个写入操作会覆盖的内容。
    set_workflow_prompt
    覆盖整个提示词,
    update_workflow_config
    替换你触碰的任何数组,
    set_workflow_cadence
    是时段的全文档PUT,
    update_workflow_config({ replace: true })
    会清空config包。先读取当前值 — 查看references/mcp-tool-surface.md
  • 在发送前了解每个写入操作接受的参数。
    update_workflow
    修改
    name
    description
    goal_statement
    、Agent身份(
    language
    timezone
    region_style
    agent_name
    agent_role
    company_name
    begin_message
    )和
    master_workflow_id
    ;每次调用必须至少携带其中一个参数,否则会因
    INVALID_INPUT
    失败。暂停状态通过
    set_workflow_active
    设置,渠道组合通过渠道绑定工具加上
    config.disabled_channels
    设置 — 两者都不是
    update_workflow
    的参数。角色和业务规则是提示词文本:
    set_workflow_prompt
    /
    set_channel_prompt
    ,而非身份字段。
  • 拒绝任何违反定律的设计,修复其形式而非用提示词措辞补偿。明确指出违反的定律:仅存在于提示词或对话历史中的必要事实(定律1);无status键的阶段变化(定律2);未通过带有命名目标Agent的边界status完成的语气、角色或工具集切换(定律3)。提示词文本是语言;字段、status和转移是结构 — 只有结构会被强制执行。
  • 未指定执行者的暂停边界是未完成的转移。要么将边界设为终端并配置
    transfer_config
    ,要么说明执行移交的任务/API/人员并验证它能移动测试潜客。
  • 当门限和自动化都需要某事实时,绝不要让该事实仅能在一个存储位置访问。若status基于
    field_x
    设置门限且
    args_template
    必须发送该值,该值必须在潜客到达该status前同时作为字段和metadata存在。
  • 任何涉及向用户发送消息或修改大量潜客的操作都先进行试运行,激活前先查看候选列表。手动运行函数可预览效果而不实际应用 — 但试运行中的出站HTTP请求是真实的;测试运行指向测试端点。
  • 激活任何客群自动化或发送消息的操作前,获取客户的明确确认。
  • 使有副作用的工具具有幂等性,并返回持久的外部操作ID。在第二次成功调用会出错的场景设置
    call_once
    ,并定义Agent在端点超时或失败时的回复内容。
  • 对于每个提议的Agent工具,说明为什么webhook、状态自动化或事件云函数无法提供相同行为。若不存在即时对话依赖,用确定性机制替代工具。
  • 对每个阶段门限工具测试两次:在允许的status前调用必须返回
    tool_not_available_in_stage
    ,资格校验后的有效调用必须到达端点。不要依赖提示词措辞作为门限。
  • 不要在不支持的界面上设计:API触发的后台任务、
    workflow_scoped
    过滤模式和CRM事件任务触发器(标签和支付事件除外)当前不可用 — 查看参考文档中的支持列表。
  • 绝不要将凭证放在函数代码或工具配置中;存储为环境变量并引用
    env.KEY
    /
    {{env.KEY}}
  • 若需求确实不匹配任何原语,明确说明缺失的内容而非强行近似。
  • 将多Agent完成视为图闭合,而非Agent数量完成。若任何预期转移缺失、未解决、附加到错误的源status或指向错误的目标ID,报告构建未完成并继续协调或明确指出失败的连接。绝不要对部分连接的系统声称成功。
  • 将知识库配置视为分配闭合。比较每个Agent的观测KB ID和优先级顺序与预期清单;附加缺失的链接并移除多余的链接,然后重新回读。绝不要从账户目录推断访问权限,且当Agent的KB集与计划不同时,绝不要声称Agent已完全配置。
  • 将渠道配置视为分配闭合。比较每个请求的渠道和选定的资源ID与构建后的账户清单和工作流配置。绝不要从“渠道启用”推断绑定,绝不要未经针对性确认重新分配已绑定的号码,写入前立即重新读取排他所有者,避免过期的批准将资源从其他现任者手中移走。当选定的发送者/号码缺失、不可用、绑定到错误Agent、被配置禁用或与
    first_contact_channel
    矛盾时,绝不要声称完成。若WhatsApp将发起外呼,列出
    APPROVED
    的问候语/开场白/legacy_greeting/出站模板,通过
    set_opening_templates
    配置,并在激活前通过
    get_template_pool
    回读。

Output

输出

Produce a configuration spec containing:
  • A variable ledger (Law 1): every fact the design needs, its
    key
    , its store (workflow field / metadata / both), how it is obtained (agent asks, intake payload, tool response), and what reads it (gate, template, filter, prompt).
  • A stage ledger (Law 2): every status key per agent with its
    entry_hint
    criterion, its gate (
    required_field_keys
    /
    transition_rules
    ), and what entering it unlocks or fires.
  • Each primitive used: its name, its trigger, and the exact configuration (JSON snippets with real field names from the reference).
  • For every workflow HTTP/MCP tool: endpoint owner, input/output schema,
    available_in_statuses
    ,
    call_once
    , response fields stored or shown to the agent, prompt invocation rule, and failure behavior.
  • For every integration action: explain why its invocation is deterministic, or explicitly justify why an agent-selected tool is unavoidable and accept the lower reliability.
  • For every transfer branch: define its source status criterion and target workflow, then specify the target's goal, prompt focus, tools, channels, contact cadence/recontact rule, and transferred fields it must not ask for again.
  • A connection manifest for every multi-agent system (Law 3): each edge's source agent, source boundary status, boundary shape (terminal transfer, or pause plus its named executor), and target agent — followed by observed read-back evidence for each edge (
    source agent + source status → target agent id
    ). The order agents were created must not affect this list.
  • A knowledge manifest for every created or edited agent, followed by observed read-back evidence for the exact assigned KB ids/names and priority order. Distinguish account-owned availability from per-agent access.
  • A channel manifest for every created or edited agent, followed by observed read-back evidence for the exact WhatsApp number, email sender, call number, and SMS number ids selected and assigned. Distinguish account availability from per-agent binding and call out any reassignment explicitly.
  • How the pieces connect (e.g. "field
    salary
    → status
    low_income
    via
    entry_hint
    transfer_config
    → agent B").
  • The ladder rungs you rejected and why, in one line each.
  • A verification checklist: the previews/dry runs to perform and the observable result that means "safe to activate."
生成包含以下内容的配置规范:
  • 变量清单(定律1):设计所需的每一个事实,其
    key
    、存储位置(工作流字段 / metadata / 两者)、获取方式(Agent询问、录入 payload、工具响应)以及读取方(门限、模板、过滤器、提示词)。
  • 阶段清单(定律2):每个Agent的所有status键,其
    entry_hint
    条件、门限(
    required_field_keys
    /
    transition_rules
    )以及进入该status后解锁或触发的内容。
  • 使用的每个原语:名称、触发条件和精确配置(包含参考文档中真实字段名的JSON片段)。
  • 每个工作流HTTP/MCP工具:端点所有者、输入/输出 schema、
    available_in_statuses
    call_once
    、存储或展示给Agent的响应字段、提示词调用规则以及失败行为。
  • 每个集成操作:说明其调用为何是确定性的,或明确说明为何必须使用Agent选择的工具并接受较低的可靠性。
  • 每个转移分支:定义其源status条件和目标工作流,然后指定目标的目标、提示词重点、工具、渠道、触达节奏/重触达规则以及必须不再询问的已转移字段。
  • 每个多Agent系统的连接清单(定律3):每个连接的源Agent、源边界status、边界形式(终端转移或暂停+命名执行者)和目标Agent — 随后是每个连接的观测回读证据(
    源Agent + 源status → 目标Agent ID
    )。Agent创建顺序不得影响该列表。
  • 每个创建或编辑的Agent的知识库清单,随后是精确分配的KB ID/名称和优先级顺序的观测回读证据。区分账户自有可用性和每个Agent的访问权限。
  • 每个创建或编辑的Agent的渠道清单,随后是选定并分配的精确WhatsApp号码、邮件发送者、呼叫号码和SMS号码ID的观测回读证据。区分账户可用性和每个Agent的绑定,并明确指出任何重新分配。
  • 各部分的连接方式(例如,“字段
    salary
    → 通过
    entry_hint
    进入status
    low_income
    transfer_config
    → Agent B”)。
  • 你拒绝的阶梯层级及原因,每条一行。
  • 验证清单:需执行的预览/试运行以及表示“可安全激活”的可观测结果。

Resources

资源

  • Read references/recipes.md when matching a customer ask to a known pattern — start from the closest recipe.
  • Read references/configuration-reference.md when writing the concrete configuration for any primitive.
  • Read references/mcp-tool-surface.md before the first write: which tool writes what, its read-back pair, what it overwrites, and which properties MCP cannot reach at all.
  • 当匹配客户需求与已知模式时,阅读references/recipes.md — 从最接近的方案开始。
  • 编写任何原语的具体配置时,阅读references/configuration-reference.md
  • 首次写入前,阅读references/mcp-tool-surface.md:每个工具写入的内容、对应的回读工具、覆盖的内容以及MCP完全无法访问的属性。