objectstack-ai

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AI Agent Design — ObjectStack AI Protocol

AI Agent设计 — ObjectStack AI协议

Expert instructions for designing AI skills, tools, and knowledge sources — and the platform agents they plug into — using the ObjectStack specification. This skill covers the Agent → Skill → Tool three-tier architecture aligned with Salesforce Agentforce, Microsoft Copilot Studio, and ServiceNow Now Assist patterns.
Edition boundary (
service-ai
→ cloud; open = MCP-only).
The in-UI AI runtime — the
ask
/
build
agents, in-product chat, and the
/api/v1/ai/*
routes (
@objectstack/service-ai
) — ships in the cloud / Enterprise distribution, not the open framework. The agent / skill / tool schemas in
@objectstack/spec/ai
stay open, so you author
*.skill.ts
/
*.tool.ts
as source either way (
*.agent.ts
is platform-internal) — but they only execute in a cloud / EE host. On the open edition there is no in-product agent: expose the app to your own AI via
@objectstack/mcp
(BYO-AI) for data query, and author metadata in source mode with an AI coding agent (Claude Code, Cursor).

关于使用ObjectStack规范设计AI技能、工具、知识源及其所接入的平台Agent的专业指导说明。本内容涵盖与Salesforce Agentforce、Microsoft Copilot Studio和ServiceNow Now Assist模式对齐的Agent→Skill→Tool三层架构。
版本边界(
service-ai
→云版本;开源版仅支持MCP)
界面内AI 运行时——
ask
/
build
Agent、产品内聊天以及
/api/v1/ai/*
路由(
@objectstack/service-ai
)——仅在云/企业发行版中提供,开源框架不包含该内容。
@objectstack/spec/ai
中的Agent/技能/工具** schema 保持开源,因此无论哪种版本,您都可以编写
*.skill.ts
/
*.tool.ts
作为源文件(
*.agent.ts
为平台内部文件)——但它们仅能在云/企业版宿主环境中执行。在
开源版中没有内置产品Agent:需通过
@objectstack/mcp
(BYO-AI)将应用接入您自己的AI以进行数据查询,并借助AI编码Agent(如Claude Code、Cursor)以
源模式**编写元数据。

When to Use This Skill

何时使用本内容

  • You need to define skills — bundles of related tools bound to the
    ask
    /
    build
    surfaces.
  • You are configuring tools for data queries, actions, or integrations.
  • You want to index ObjectStack data as a knowledge source for RAG retrieval.
  • You are choosing and configuring LLM models (model registry).
  • You need to read or review agent configuration — platform-internal; third parties extend agents via skills, not by authoring them.

  • 您需要定义技能——绑定到
    ask
    /
    build
    界面的相关工具集合。
  • 您正在配置用于数据查询、操作或集成的工具
  • 您希望将ObjectStack数据索引为RAG检索的知识源
  • 您正在选择和配置LLM模型(模型注册表)。
  • 您需要读取或审核Agent配置——平台内部组件;第三方通过技能扩展Agent,而非编写Agent文件。

Three-Tier Architecture

三层架构

Agent  →  Skill  →  Tool
  │         │         │
  │         │         └─ Atomic operation (query, action, flow, API call)
  │         └─ Capability bundle with instructions & trigger phrases
  └─ Autonomous actor with role, instructions, and guardrails
Agent  →  Skill  →  Tool
  │         │         │
  │         │         └─ 原子操作(查询、动作、流程、API调用)
  │         └─ 包含指令和触发短语的能力集合
  └─ 具备角色、指令和防护规则的自主执行主体

Why Three Tiers?

为何采用三层架构?

TierAnalogyReuse Level
AgentJob role (e.g., "Help Desk Agent")Per use-case
SkillCompetency (e.g., "Case Management")Across agents
ToolSpecific operation (e.g., "create_record")Across skills
Best practice: Always model via Skills first. Direct tool assignment to agents is supported but considered legacy. Skills provide better discoverability, instruction scoping, and reuse.
层级类比复用级别
Agent职位角色(如“客服台Agent”)按用例划分
Skill能力资质(如“案例管理”)跨Agent复用
Tool具体操作(如“create_record”)跨技能复用
最佳实践: 始终优先通过Skill进行建模。直接为Agent分配工具的方式虽被支持,但已被视为遗留方案。Skill具备更好的可发现性、指令范围控制和复用性。

Built-in agents:
ask
&
build
(ADR-0063 / ADR-0064)

内置Agent:
ask
&
build
(ADR-0063 / ADR-0064)

The runtime ships exactly two platform agents, bound by surface — the user never picks from a roster; the surface they are in selects the agent:
  • ask
    — the data product (≈ Claude Chat). Conversational read / query / explore over records, plus running the business actions the app already exposes. End-user audience, RLS-bounded. Canonical id
    ask
    (
    ASK_AGENT_NAME
    ). Cloud / Enterprise — the
    ask
    runtime ships in the closed cloud AI runtime (
    @objectstack/service-ai
    ); it is the implicit copilot for any cloud / EE app that does not pin
    app.defaultAgent
    . (Open editions have no in-product
    ask
    ; use MCP.)
  • build
    — the authoring product (≈ Claude Code). Agentic authoring of metadata (objects, fields, views, flows) through plan → draft → verify → publish. Builder audience, governance-gated. Canonical id
    build
    . Cloud-only · paid — ships in the cloud AI Studio plugin; Studio pins it via
    app.defaultAgent
    .
There is no per-turn intent classifier: a
build
-shaped request arriving at
ask
is declined and redirected to the Builder, never silently re-routed into authoring (ADR-0063 §1/§5).
Legacy names are aliases only.
data_chat
ask
and
metadata_assistant
build
resolve through the alias table for old bookmarks and persisted
agent_id
s; they are not vocabulary — always write
ask
/
build
.
*.agent.ts
is closed to third parties (
agent
type is
allowRuntimeCreate:false, allowOrgOverride:false
): you extend the platform with skills, never by authoring an agent (ADR-0063 §2).
运行时仅提供两个平台Agent,按界面绑定——用户无需从列表中选择,而是由当前所在界面自动选择对应的Agent:
  • ask
    —— 数据产品(类似Claude Chat)。支持对记录进行对话式读取/查询/探索,以及执行应用已暴露的业务动作。面向终端用户,受RLS权限限制。标准ID为
    ask
    ASK_AGENT_NAME
    )。云/企业版专属——
    ask
    运行时包含在闭源云AI运行时(
    @objectstack/service-ai
    )中;对于未设置
    app.defaultAgent
    的云/企业版应用,它是默认的副驾驶助手。(开源版无内置
    ask
    Agent;需使用MCP。)
  • build
    —— 创作产品(类似Claude Code)。通过计划→起草→验证→发布的流程,以Agent方式创作元数据(对象、字段、视图、流程)。面向构建者,受治理规则管控。标准ID为
    build
    。仅云付费版提供——包含在云AI Studio插件中;Studio通过
    app.defaultAgent
    指定使用该Agent。
系统无逐轮意图分类器:发送到
ask
build
类请求会被拒绝并引导至Builder界面,绝不会静默路由到创作流程(ADR-0063 §1/§5)。
旧名称仅为别名。
data_chat
ask
metadata_assistant
build
仅用于兼容旧书签和持久化的
agent_id
;它们不属于标准词汇——请始终使用
ask
/
build
*.agent.ts
对第三方关闭(
agent
类型设置
allowRuntimeCreate:false, allowOrgOverride:false
):您需通过技能扩展平台,而非编写Agent(ADR-0063 §2)。

Skill → agent affinity: the
surface
field (ADR-0063 §3)

技能→Agent关联性:
surface
字段(ADR-0063 §3)

Every skill declares which surface it binds to via
surface: 'ask' | 'build' | 'both'
(defaults to
'ask'
). A skill may bind only to an agent whose surface it matches;
'both'
binds to either. The runtime enforces this in
resolveActiveSkills
at load time — an incompatible binding is a fast load error, not a silent mis-scope. An agent's tool set is the union of its surface-compatible skills' tools — there is no global fall-through (ADR-0064), so
ask
cannot author by construction.
The built-in skills and their affinities:
Skill
surface
OwnsEdition
schema_reader
both
list_objects
,
describe_object
,
query_data
OSS
data_explorer
ask
query_records
,
get_record
,
aggregate_data
,
visualize_data
OSS
actions_executor
ask
action_*
(the business actions an object exposes)
OSS
metadata_authoring
+
solution_design
build
metadata draft / verify / publish + blueprint propose / applycloud only
To grant data exploration to your own (platform-internal) agent, add
data_explorer
/
schema_reader
to its
skills[]
; deactivating a skill (
active: false
) revokes that capability for every agent that references it.
surface:'build'
skills are inert on OSS — by design, not a bug.
The open single-env framework ships only the
ask
agent;
metadata_authoring
/
solution_design
(and any third-party
surface:'build'
skill) are supplied by the cloud AI Studio plugin and simply do not resolve in OSS. A
build
-intent turn on OSS degrades gracefully ("authoring lives in the cloud Build assistant") instead of dead-ending — this is intentional tiering. Do not assume authoring tools resolve in the open framework.
visualize_data
:
the only built-in tool that draws a chart — it aggregates an object and emits an inline
data-chart
part. Auto-registered only when an analytics service (
IAnalyticsService
) is wired;
query_data
/
aggregate_data
return numbers, not charts.
Ops: set
AI_DAILY_USER_MESSAGES=<N>
to cap user turns per user per day (backed by the
ai_usage_daily
object; no-op if unset). Adapter health is observable at
GET /api/v1/ai/status
; invalid
ai
settings are rejected at save time.

每个技能通过
surface: 'ask' | 'build' | 'both'
(默认值为
'ask'
)声明其绑定的界面。技能仅能绑定与之界面匹配的Agent;
'both'
表示可绑定任意界面。运行时在加载时通过
resolveActiveSkills
强制执行此规则——不兼容的绑定会触发快速加载错误,而非静默失效。Agent的工具集是其所有兼容界面技能的工具的并集——不存在全局回退机制(ADR-0064),因此
ask
Agent本质上无法执行创作操作。
内置技能及其关联性:
技能
surface
包含工具版本
schema_reader
both
list_objects
,
describe_object
,
query_data
开源版
data_explorer
ask
query_records
,
get_record
,
aggregate_data
,
visualize_data
开源版
actions_executor
ask
action_*
(对象暴露的业务动作)
开源版
metadata_authoring
+
solution_design
build
元数据起草/验证/发布 + 蓝图提议/应用仅云版本
若要为您的(平台内部)Agent授予数据探索能力,需将
data_explorer
/
schema_reader
添加到其
skills[]
中;停用技能(
active: false
)会撤销所有引用该技能的Agent的对应能力。
surface:'build'
技能在开源版中无效——这是设计使然,而非Bug。
开源单环境框架仅提供
ask
Agent;
metadata_authoring
/
solution_design
(以及任何第三方
surface:'build'
技能)由云AI Studio插件提供,在开源版中无法解析。开源版中收到
build
意图请求时会优雅降级(“创作功能位于云Build助手中”),而非直接失败——这是有意的分层设计。请勿假设创作工具在开源框架中可用。
visualize_data
唯一内置的绘图工具——它聚合对象并输出内嵌的
data-chart
部分。仅在接入分析服务(
IAnalyticsService
)时自动注册;
query_data
/
aggregate_data
仅返回数值,不生成图表。
运维配置: 设置
AI_DAILY_USER_MESSAGES=<N>
可限制每个用户每日的交互轮次(由
ai_usage_daily
对象支持;未设置时无限制)。适配器健康状态可通过
GET /api/v1/ai/status
查看;无效的
ai
设置会在保存时被拒绝。

Agent Configuration

Agent配置

Reference only — third parties do not author agents. The
agent
type is closed (
allowRuntimeCreate:false
; ADR-0063 §2): the platform ships exactly
ask
and
build
, maintained by platform / cloud plugin authors. You extend the platform with skills + tools (and knowledge sources) — never by adding an agent. This section documents
AgentSchema
for reading existing agents and for platform-internal work.
仅供参考——第三方无需编写Agent。
agent
类型为闭源(
allowRuntimeCreate:false
;ADR-0063 §2):平台仅提供
ask
build
两个Agent,由平台/云插件维护者负责维护。您需通过技能+工具(以及知识源)扩展平台——绝不能通过添加Agent的方式。本节记录
AgentSchema
用于读取现有Agent配置及平台内部开发。

Required Properties

必填属性

PropertyTypeDescription
name
snake_case
Unique agent identifier
label
stringHuman-readable name
role
stringAgent's persona/role description
instructions
stringSystem prompt — detailed behavioural guidance
属性类型描述
name
snake_case
唯一Agent标识符
label
string人类可读名称
role
stringAgent的角色/人设描述
instructions
string系统提示词——详细的行为指导

Important Optional Properties

重要可选属性

PropertyPurpose
skills
Array of skill names — primary capability model
tools
Direct tool references — legacy fallback
surface
'ask' | 'build'
— the product surface this agent is (default
'ask'
)
model
LLM model configuration —
provider
,
model
,
temperature
,
maxTokens
,
topP
knowledge
REMOVED in protocol 17 (#3896 close-out) — declaring sources/indexes on an agent never scoped retrieval (
search_knowledge
takes
sourceIds
from the LLM's tool-call arguments). Restrict at the knowledge-service/source level; describe intended grounding in
instructions
guardrails
maxTokensPerInvocation
,
maxExecutionTimeSec
,
blockedTopics
structuredOutput
Output format (JSON schema, regex, etc.)
planning
Autonomous reasoning —
maxIterations
(default 10)
memory
longTerm
persistence +
reflectionInterval
permissions
Permission-set capabilities required to use the agent
active
Enable/disable the agent
There is no top-level
temperature
/
maxTokens
on an agent — sampling parameters live under
model
(
AIModelConfigSchema
).
属性用途
skills
技能名称数组——核心能力模型
tools
直接工具引用——遗留回退方案
surface
'ask' | 'build'
—— Agent对应的产品界面(默认
'ask'
model
LLM模型配置——
provider
,
model
,
temperature
,
maxTokens
,
topP
knowledge
协议17版本中移除(#3896收尾工作)——在Agent上声明源/索引无法限定检索范围(
search_knowledge
从LLM的工具调用参数中获取
sourceIds
)。请在知识服务/源层面进行限制;在
instructions
中描述预期的基础信息
guardrails
maxTokensPerInvocation
,
maxExecutionTimeSec
,
blockedTopics
structuredOutput
输出格式(JSON schema、正则表达式等)
planning
自主推理——
maxIterations
(默认值10)
memory
longTerm
持久化 +
reflectionInterval
permissions
使用Agent所需的权限集能力
active
启用/禁用Agent
Agent**无顶层
temperature
/
maxTokens
**参数——采样参数位于
model
AIModelConfigSchema
)下。

Agent Example

Agent示例

<!-- os:check -->
typescript
import { defineAgent } from '@objectstack/spec';

export default defineAgent({
  name: 'support_tier_1',
  label: 'First Line Support',
  role: 'Help Desk Assistant for customer support cases',
  instructions: `
    You are a friendly and professional help desk assistant.
    
    RULES:
    - Always greet the customer by name if available.
    - Search the knowledge base before creating a new case.
    - Escalate to a human agent if the issue is critical or security-related.
    - Never share internal system details with customers.
    - Respond in the customer's preferred language.
  `,
  skills: ['case_management', 'knowledge_search'],
  model: {
    provider: 'openai',
    model: 'gpt-4o',
    temperature: 0.3,
  },
  guardrails: {
    blockedTopics: ['internal_pricing', 'employee_data'],   // forbidden topics / action names
    maxTokensPerInvocation: 8000,                            // token budget per invocation
    maxExecutionTimeSec: 60,                                 // wall-clock cap per invocation
  },
});

<!-- os:check -->
typescript
import { defineAgent } from '@objectstack/spec';

export default defineAgent({
  name: 'support_tier_1',
  label: '一线客服',
  role: '客户支持案例的客服台助手',
  instructions: `
    您是一位友好且专业的客服台助手。
    
    规则:
    - 若可用,请始终称呼客户姓名。
    - 创建新案例前先搜索知识库。
    - 若问题严重或涉及安全,请升级给人工Agent。
    - 绝不能向客户透露内部系统细节。
    - 使用客户偏好的语言回复。
  `,
  skills: ['case_management', 'knowledge_search'],
  model: {
    provider: 'openai',
    model: 'gpt-4o',
    temperature: 0.3,
  },
  guardrails: {
    blockedTopics: ['internal_pricing', 'employee_data'],   // 禁止的主题/动作名称
    maxTokensPerInvocation: 8000,                            // 每次调用的token预算
    maxExecutionTimeSec: 60,                                 // 每次调用的最长执行时间(秒)
  },
});

Skill Configuration

技能配置

A Skill is a named bundle of tools with dedicated instructions and trigger conditions.
Skill是包含专用指令和触发条件的命名工具集合。

Required Properties

必填属性

PropertyTypeDescription
name
snake_case
Unique skill identifier (
/^[a-z_][a-z0-9_]*$/
)
label
stringHuman-readable name
tools
string[]
Tool names this skill grants access to (trailing wildcard allowed, e.g.
action_*
)
属性类型描述
name
snake_case
唯一技能标识符(
/^[a-z_][a-z0-9_]*$/
label
string人类可读名称
tools
string[]
该技能授予访问权限的工具名称(支持后缀通配符,如
action_*

Important Optional Properties

重要可选属性

PropertyPurpose
surface
'ask' | 'build' | 'both'
— agent surface affinity (default
'ask'
; see above)
description
What the skill does — helps the agent decide when to use it
instructions
LLM prompt guidance specific to this skill's context
triggerPhrases
Natural language phrases that activate the skill
triggerConditions
Programmatic activation rules
active
Is the skill enabled (default:
true
)
A skill has no
permissions
key
— it was removed in 16.x. Skill invocation was never gated by it (the registry reads only
active
/
triggerConditions
/
tools
), and a security-shaped field that enforces nothing is worse than no field at all. Gate access at the agent instead —
access
/
permissions
on
defineAgent
are enforced at the chat route — or on the underlying actions the skill's tools call (permission sets, ADR-0066).
属性用途
surface
'ask' | 'build' | 'both'
—— Agent界面关联性(默认
'ask'
;详见上文)
description
技能功能描述——帮助Agent判断何时使用该技能
instructions
针对该技能场景的LLM提示指导
triggerPhrases
触发技能的自然语言短语
triggerConditions
程序化激活规则
active
技能是否启用(默认:
true
技能
permissions
字段
——该字段在16.x版本中移除。技能调用从未受此字段限制(注册表仅读取
active
/
triggerConditions
/
tools
),一个无实际作用的安全相关字段比没有字段更糟。请在Agent层面控制访问权限——
defineAgent
中的
access
/
permissions
会在聊天路由层面强制执行——或在技能工具调用的底层动作上进行控制(权限集,ADR-0066)。

Skill Example

技能示例

<!-- os:check -->
typescript
import { defineSkill } from '@objectstack/spec';

export default defineSkill({
  name: 'case_management',
  label: 'Case Management',
  description: 'Create, update, query, and escalate support cases.',
  instructions: `
    When managing cases:
    - Always check for duplicate cases before creating a new one.
    - Set priority based on customer tier: Enterprise → High, Pro → Medium, Free → Low.
    - Escalated cases must include a summary of actions already taken.
  `,
  tools: [
    'query_support_case',
    'create_support_case',
    'update_support_case',
    'escalate_case',
  ],
  triggerConditions: [
    { field: 'objectName', operator: 'eq', value: 'support_case' },
  ],
  active: true,
});
<!-- os:check -->
typescript
import { defineSkill } from '@objectstack/spec';

export default defineSkill({
  name: 'case_management',
  label: '案例管理',
  description: '创建、更新、查询和升级支持案例。',
  instructions: `
    管理案例时:
    - 创建新案例前务必检查是否存在重复案例。
    - 根据客户等级设置优先级:企业版→高,专业版→中,免费版→低。
    - 升级的案例必须包含已执行操作的摘要。
  `,
  tools: [
    'query_support_case',
    'create_support_case',
    'update_support_case',
    'escalate_case',
  ],
  triggerConditions: [
    { field: 'objectName', operator: 'eq', value: 'support_case' },
  ],
  active: true,
});

Trigger Conditions

触发条件

OperatorMeaning
eq
Equals
neq
Not equals
in
Value is in array
not_in
Value is not in array
contains
String contains substring

操作符含义
eq
等于
neq
不等于
in
值在数组中
not_in
值不在数组中
contains
字符串包含子串

Tool Configuration

工具配置

Tools are the atomic operations that skills expose to agents.
工具是技能向Agent暴露的原子操作。

First-Class Tool Metadata (
defineTool
)

一等工具元数据(
defineTool

A tool authored as metadata (
type: 'tool'
,
*.tool.ts
) is validated by
ToolSchema
: required
name
/
label
/
description
, a JSON Schema
parameters
object, plus optional
objectName
and
outputSchema
.
ToolSchema
is strict — an unknown key (a typo, or a retired key) is a parse error, not a silent strip. Retired in the #3896 close-out:
category
,
permissions
,
active
and
builtIn
(all were authorable and inert;
permissions
gated nothing and
active: false
withdrew nothing — the rejection message carries each key's replacement), joining
requiresConfirmation
(#3715).
<!-- os:check -->
typescript
import { defineTool } from '@objectstack/spec';

export default defineTool({
  name: 'create_case',
  label: 'Create Support Case',
  description: 'Creates a new support case record',
  parameters: {
    type: 'object',
    properties: {
      subject: { type: 'string', description: 'Case subject' },
      priority: { type: 'string', enum: ['low', 'medium', 'high'] },
    },
    required: ['subject'],
  },
  objectName: 'support_case',
});
To gate what a tool can do, gate the underlying action (
action.requiredPermissions
, ADR-0066) or the objects it touches; to withdraw a tool, remove it from the skills/agents that reference it. Categorization, if you need it, belongs on the action side (
action.ai.category
— a live, enforced surface).
Tool metadata is a read-only projection — not an execution entry point.
ToolSchema
has no
handler
/
implementation
field, and no framework executor loads a metadata-authored tool. The runtime executes a separately-registered
AIToolDefinition
(cloud
@objectstack/service-ai
); tool metadata is a one-way projection for Studio / discovery. Do not expect a hand-authored tool to run in the open edition (liveness audit #1878/#1892).
以元数据方式编写的工具(
type: 'tool'
*.tool.ts
)会被
ToolSchema
验证:必填
name
/
label
/
description
,一个JSON Schema格式的
parameters
对象,以及可选的
objectName
outputSchema
ToolSchema
严格模式——未知键(如拼写错误或已废弃的键)会导致解析错误,而非静默忽略。#3896收尾工作中已废弃的字段:
category
,
permissions
,
active
builtIn
(这些字段均可编写但无实际作用;
permissions
无限制作用,
active: false
无法禁用工具——错误信息会包含每个字段的替代方案),同时废弃的还有
requiresConfirmation
(#3715)。
<!-- os:check -->
typescript
import { defineTool } from '@objectstack/spec';

export default defineTool({
  name: 'create_case',
  label: '创建支持案例',
  description: '创建新的支持案例记录',
  parameters: {
    type: 'object',
    properties: {
      subject: { type: 'string', description: '案例主题' },
      priority: { type: 'string', enum: ['low', 'medium', 'high'] },
    },
    required: ['subject'],
  },
  objectName: 'support_case',
});
若要限制工具的操作范围,请在底层动作(
action.requiredPermissions
,ADR-0066)或其涉及的对象上进行控制;若要停用工具,请从引用它的技能/Agent中移除。如需分类,请在动作层面设置(
action.ai.category
——一个有效的、受强制执行的字段)。
工具元数据是只读投影——而非执行入口。
ToolSchema
handler
/
implementation
字段,框架执行器不会加载以元数据编写的工具。运行时执行的是单独注册的
AIToolDefinition
(云版本
@objectstack/service-ai
);工具元数据仅用于Studio/发现功能的单向投影。请勿期望手动编写的工具能在开源版中运行(活性审计#1878/#1892)。

Inline Agent
tools[]
(legacy)

Agent内联
tools[]
(遗留方案)

Entries in an agent's inline
tools[]
array are a different, legacy shape (
AIToolSchema
):
{ type: 'action' | 'flow' | 'query' | 'vector_search', name, description? }
— references to existing actions / flows / queries, not tool definitions. Prefer skills + first-class tool names.
Agent内联
tools[]
数组中的条目是不同的遗留格式
AIToolSchema
):
{ type: 'action' | 'flow' | 'query' | 'vector_search', name, description? }
——引用现有动作/流程/查询,而非工具定义。优先使用技能+一等工具名称的方式。

Auto-Exposed Actions

自动暴露的动作

Cloud / EE runtime.
registerActionsAsTools()
,
AIServicePlugin
, and the HITL approval queue below ship in
@objectstack/service-ai
— the closed cloud / Enterprise runtime, not an open package. On the open edition, expose actions to your own AI via
@objectstack/mcp
instead.
You usually don't author tool definitions by hand for action invocation. Every
Action
you attach to an object via
defineObject({ actions: [...] })
is auto-exposed as a tool named
action_<actionName>
by
registerActionsAsTools()
(invoked from
AIServicePlugin
).
Three action types dispatch headlessly:
action.type
DispatchWiring
script
IDataEngine.executeAction(object, target, ctx)
— same as Studio's row toolbar
none
api
HTTP call to
action.target
(
fetch
-based by default)
AIServicePlugin({ apiActionBaseUrl, apiActionHeaders })
or custom
apiClient
flow
IAutomationService.execute(target, { triggerData })
automation
service registered with the kernel
Skipped automatically:
  • UI-only types (
    url
    ,
    modal
    ,
    form
    ).
  • Dangerous variants (
    confirmText
    set,
    mode: 'delete'
    ,
    variant: 'danger'
    ) — unless the plugin is started with
    enableActionApproval: true
    , in which case they route through the HITL approval queue (see below).
  • Owner opt-outs (
    aiExposed: false
    ).
type:'api'
body assembly
(last wins): user params →
recordIdParam
(using
recordIdField
, default
'id'
) →
bodyExtra
.
bodyShape: { wrap: 'data' }
nests user params under
data
while keeping
recordIdParam
flat.
Use
actionSkipReason(action, ctx)
(exported from
@objectstack/service-ai
— cloud-only, not importable on the open edition) when authoring an action and you want to know why it isn't surfacing in chat. Studio's "AI exposure" diagnostics use the same predicate. Pair with
actionRequiresApproval(action)
to know whether a registered action will be routed through HITL.
云/企业版运行时专属。
registerActionsAsTools()
AIServicePlugin
以及下文的人工审核队列均包含在
@objectstack/service-ai
中——闭源云/企业版运行时,而非开源包。在开源版中,请通过
@objectstack/mcp
将动作暴露给您自己的AI。
通常,您无需手动编写工具定义来调用动作。通过
defineObject({ actions: [...] })
附加到对象的每个
Action
都会被
registerActionsAsTools()
(由
AIServicePlugin
调用)自动暴露为名为
action_<actionName>
的工具。
三种动作类型支持无头调度:
action.type
调度方式配置
script
IDataEngine.executeAction(object, target, ctx)
——与Studio行工具栏相同
无需额外配置
api
action.target
发起HTTP调用(默认基于
fetch
AIServicePlugin({ apiActionBaseUrl, apiActionHeaders })
或自定义
apiClient
flow
IAutomationService.execute(target, { triggerData })
内核已注册
automation
服务
自动跳过的动作:
  • 仅UI类型(
    url
    ,
    modal
    ,
    form
    )。
  • 危险变体(设置了
    confirmText
    mode: 'delete'
    variant: 'danger'
    )——除非插件启动时设置
    enableActionApproval: true
    ,此时这些动作会进入人工审核队列(详见下文)。
  • 所有者选择不暴露的动作(
    aiExposed: false
    )。
type:'api'
请求体组装
(后设置的值覆盖先设置的):用户参数→
recordIdParam
(使用
recordIdField
,默认
'id'
)→
bodyExtra
bodyShape: { wrap: 'data' }
会将用户参数嵌套在
data
下,同时保持
recordIdParam
为顶层字段。
编写动作时,若想了解动作未在聊天中显示的原因,可使用
actionSkipReason(action, ctx)
(从
@objectstack/service-ai
导出——仅云版本可用,开源版无法导入)。Studio的“AI暴露”诊断功能使用相同的判断逻辑。可搭配
actionRequiresApproval(action)
判断已注册动作是否需要进入人工审核流程。

Human-In-The-Loop approval

人工审核(Human-In-The-Loop)

Cloud / EE runtime. The HITL approval queue is part of
@objectstack/service-ai
and is not available in the open framework.
ts
kernel.use(new AIServicePlugin({
  enableActionApproval: true,   // opt in; default is false
  apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL,
}));
Flow:
  1. LLM picks
    action_delete_task
    → runtime persists an
    ai_pending_actions
    row and returns
    { status: 'pending_approval', pendingActionId }
    .
  2. Operator triages via Studio's AI Pending Actions inbox (or the REST endpoints:
    GET/POST /api/v1/ai/pending-actions/...
    ).
  3. Approve → service re-runs the action via the pre-registered bypass-approval dispatcher; row transitions to
    executed
    /
    failed
    .
  4. Reject → row transitions to
    rejected
    with an optional reason.
Programmatic API on
IAIService
:
proposePendingAction
,
approvePendingAction
,
rejectPendingAction
,
listPendingActions
. All are optional (returns clear error when no
IDataEngine
is wired).

云/企业版运行时专属。 人工审核队列是
@objectstack/service-ai
的一部分,开源框架不提供此功能。
ts
kernel.use(new AIServicePlugin({
  enableActionApproval: true,   // 选择启用;默认false
  apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL,
}));
流程:
  1. LLM选择
    action_delete_task
    →运行时创建
    ai_pending_actions
    记录并返回
    { status: 'pending_approval', pendingActionId }
  2. 操作员通过Studio的AI待处理动作收件箱(或REST端点:
    GET/POST /api/v1/ai/pending-actions/...
    )进行分类处理。
  3. 批准→服务通过预注册的绕过审核调度器重新执行动作;记录状态变为
    executed
    /
    failed
  4. 拒绝→记录状态变为
    rejected
    并可附带拒绝原因。
IAIService
提供的编程式API:
proposePendingAction
,
approvePendingAction
,
rejectPendingAction
,
listPendingActions
。所有API均为可选(未接入
IDataEngine
时返回明确错误)。

Knowledge Sources (RAG)

知识源(RAG)

The platform's RAG primitive is the KnowledgeSource (
KnowledgeSourceSchema
in
@objectstack/spec/ai
): declarative metadata pairing what to index with the id of an
IKnowledgeAdapter
that does the work. Sources are registered at runtime via
IKnowledgeService.registerSource()
(there is no
defineStack
collection for them), and the
search_knowledge
tool exposes registered sources to agents.
平台的RAG基础组件是KnowledgeSource
@objectstack/spec/ai
中的
KnowledgeSourceSchema
):声明式元数据,将待索引内容与执行索引工作的
IKnowledgeAdapter
的ID配对。源在运行时通过
IKnowledgeService.registerSource()
注册(无
defineStack
集合用于存储),
search_knowledge
工具将已注册的源暴露给Agent。

KnowledgeSource Structure

KnowledgeSource结构

PropertyPurpose
id
Snake_case source id
label
/
description
Display metadata
adapter
Adapter id (e.g.
'ragflow'
,
'memory'
), resolved via
IKnowledgeService.registerAdapter
adapterConfig
Adapter-specific configuration (opaque to the service)
source
What gets indexed — discriminated on
kind
:
'object'
|
'file'
|
'http'
embedding
Optional
EmbeddingModelSchema
ref (
provider
,
model
,
dimensions
) — adapters that manage embeddings internally (RAGFlow, Dify, Vectara) may ignore it
vectorStore
Optional
VectorStoreSchema
ref (
provider
,
collection
) — same caveat
refresh
onRecordChange
(default
true
for object sources) + optional
cron
(surfaced for an external scheduler, not self-scheduled)
aiExposed
Whether
search_knowledge
may expose this source to agents (default
true
)
Source kinds:
source.kind
Fields
object
object
,
contentFields[]
(min 1;
*
= every readable text field),
metadataFields?
,
where?
(ObjectQL
where
syntax)
file
prefix
(storage prefix, e.g.
kb/handbooks/
),
mimeTypes?
http
urls[]
,
userAgent?
属性用途
id
蛇形命名的源ID
label
/
description
显示元数据
adapter
适配器ID(如
'ragflow'
,
'memory'
),通过
IKnowledgeService.registerAdapter
解析
adapterConfig
适配器专属配置(服务无需理解其内容)
source
待索引内容——按
kind
区分:
'object'
|
'file'
|
'http'
embedding
可选的
EmbeddingModelSchema
引用(
provider
,
model
,
dimensions
)——自行管理嵌入的适配器(如RAGFlow、Dify、Vectara)可忽略此字段
vectorStore
可选的
VectorStoreSchema
引用(
provider
,
collection
)——同上
refresh
onRecordChange
(对象源默认
true
) + 可选的
cron
(供外部调度器使用,非自调度)
aiExposed
search_knowledge
是否可将此源暴露给Agent(默认
true
源类型:
source.kind
字段
object
object
,
contentFields[]
(至少1个;
*
表示所有可读文本字段),
metadataFields?
,
where?
(ObjectQL
where
语法)
file
prefix
(存储前缀,如
kb/handbooks/
),
mimeTypes?
http
urls[]
,
userAgent?

Knowledge Source Example

知识源示例

<!-- os:check -->
typescript
import { KnowledgeSourceSchema, type KnowledgeSource } from '@objectstack/spec/ai';

export const supportKb: KnowledgeSource = KnowledgeSourceSchema.parse({
  id: 'support_kb',
  label: 'Support Knowledge Base',
  adapter: 'ragflow',                       // or 'memory' for dev/test
  source: {
    kind: 'object',
    object: 'kb_article',
    contentFields: ['title', 'body'],       // concatenated into document content
    metadataFields: ['category', 'owner_id'], // projected for search-time filtering
    where: { published: true },             // index published articles only
  },
  refresh: { onRecordChange: true },        // re-index on record.* events
});
Chunking, top-K, score thresholds, and rerankers are NOT platform metadata. The spec deliberately scopes them out (
embedding.zod.ts
): chunking strategies, retrieval pipelines, and RAG orchestration belong to the adapter (
adapterConfig
) or application code. The platform only carries the embed + vector primitives so any RAG strategy can be built on top.
<!-- os:check -->
typescript
import { KnowledgeSourceSchema, type KnowledgeSource } from '@objectstack/spec/ai';

export const supportKb: KnowledgeSource = KnowledgeSourceSchema.parse({
  id: 'support_kb',
  label: '支持知识库',
  adapter: 'ragflow',                       // 开发/测试时可使用'memory'
  source: {
    kind: 'object',
    object: 'kb_article',
    contentFields: ['title', 'body'],       // 拼接为文档内容
    metadataFields: ['category', 'owner_id'], // 投影供搜索时过滤使用
    where: { published: true },             // 仅索引已发布的文章
  },
  refresh: { onRecordChange: true },        // 记录变更时重新索引
});
分块、Top-K、分数阈值和重排序器不属于平台元数据。 规范有意将这些内容排除在外(
embedding.zod.ts
):分块策略、检索管道和RAG编排属于适配器(
adapterConfig
)或应用代码的范畴。平台仅提供嵌入和向量基础组件,以便在其上构建任意RAG策略。

Knowledge Source Best Practices

知识源最佳实践

  1. Filter with
    where
    .
    Index only published/active records (
    where: { published: true }
    ) so draft or archived content never enters the index.
  2. Index only meaningful text via
    contentFields
    .
    Do not include system fields or IDs; use
    *
    (all readable text fields) sparingly.
  3. Project filter fields into
    metadataFields
    (e.g.
    status
    ,
    owner_id
    ,
    tags
    ) so searches can be narrowed at query time.
  4. Hide with
    aiExposed: false
    when a source should be indexed but not agent-searchable.
  5. Tune relevance in the adapter, not the metadata. Top-K, thresholds, and reranking are configured in your RAG backend (via
    adapterConfig
    ), not in ObjectStack metadata.

  1. 使用
    where
    过滤。
    仅索引已发布/激活的记录(
    where: { published: true }
    ),确保草稿或归档内容不会进入索引。
  2. 通过
    contentFields
    仅索引有意义的文本。
    不要包含系统字段或ID;谨慎使用
    *
    (所有可读文本字段)。
  3. 将过滤字段投影到
    metadataFields
    (如
    status
    ,
    owner_id
    ,
    tags
    ),以便在查询时缩小搜索范围。
  4. 设置
    aiExposed: false
    隐藏源
    ,当需要索引但不希望Agent可搜索时使用。
  5. 在适配器中调整相关性,而非元数据。 Top-K、阈值和重排序需在RAG后端配置(通过
    adapterConfig
    ),而非ObjectStack元数据。

Model Configuration

模型配置

Supported Providers

支持的提供商

ProviderModelsUse Case
openai
GPT-4o, GPT-4o-mini, o1, o3-miniGeneral purpose, reasoning
anthropic
Claude Sonnet 4, Claude HaikuLong context, safety
azure_openai
Same as OpenAI, enterprise managedCompliance, data residency
local
Ollama, vLLM, llama.cppOn-premise, air-gapped
The inline agent
model.provider
enum is the narrow set above (
openai
/
azure_openai
/
anthropic
/
local
). Model-registry entries (
ModelProviderSchema
) accept a wider set: also
google
,
cohere
,
huggingface
,
custom
.
提供商模型使用场景
openai
GPT-4o, GPT-4o-mini, o1, o3-mini通用场景、推理
anthropic
Claude Sonnet 4, Claude Haiku长上下文、安全性
azure_openai
与OpenAI相同,企业托管合规性、数据驻留
local
Ollama, vLLM, llama.cpp本地部署、离线环境
Agent内联的
model.provider
枚举仅包含上述窄范围选项(
openai
/
azure_openai
/
anthropic
/
local
)。模型注册表条目(
ModelProviderSchema
)支持更广泛的提供商:还包括
google
,
cohere
,
huggingface
,
custom

Model Selection Guidelines

模型选择指南

ScenarioRecommended
Complex reasoning, multi-step planningGPT-4o / Claude Sonnet 4
High-volume, low-latencyGPT-4o-mini / Claude Haiku
Sensitive data, on-premiseLocal models via Ollama
Structured data extractionAny model +
structuredOutput
config
场景推荐模型
复杂推理、多步骤规划GPT-4o / Claude Sonnet 4
高并发、低延迟GPT-4o-mini / Claude Haiku
敏感数据、本地部署通过Ollama使用本地模型
结构化数据提取任意模型 +
structuredOutput
配置

Temperature Guidelines

Temperature参数指南

ValueUse Case
0.0–0.3
Factual Q&A, data extraction, code generation
0.3–0.7
Conversational agents, customer support
0.7–1.0
Creative writing, brainstorming
> 1.0
Experimental / highly creative (use with caution)

使用场景
0.0–0.3
事实问答、数据提取、代码生成
0.3–0.7
对话式Agent、客户支持
0.7–1.0
创意写作、头脑风暴
> 1.0
实验性/高创意场景(谨慎使用)

Structured Output

结构化输出

Force the agent to respond in a specific format:
typescript
structuredOutput: {
  format: 'json_schema',
  schema: {
    type: 'object',
    properties: {
      summary: { type: 'string' },
      priority: { type: 'string', enum: ['low', 'medium', 'high'] },
      action_items: { type: 'array', items: { type: 'string' } },
    },
    required: ['summary', 'priority'],
  },
  strict: true,     // enforce exact schema compliance (default: false)
  maxRetries: 3,    // max retries on validation failure (default: 3)
}
On validation failure the runtime retries by default (
retryOnValidationFailure: true
). Optional extras:
fallbackFormat
and a
transformPipeline
of post-processing steps (
trim
,
parse_json
,
validate
,
coerce_types
). There is no
retry
object — the knobs are
retryOnValidationFailure
+
maxRetries
.

强制Agent以特定格式响应:
typescript
structuredOutput: {
  format: 'json_schema',
  schema: {
    type: 'object',
    properties: {
      summary: { type: 'string' },
      priority: { type: 'string', enum: ['low', 'medium', 'high'] },
      action_items: { type: 'array', items: { type: 'string' } },
    },
    required: ['summary', 'priority'],
  },
  strict: true,     // 强制严格符合schema(默认:false)
  maxRetries: 3,    // 验证失败时的最大重试次数(默认:3)
}
验证失败时,运行时默认会重试(
retryOnValidationFailure: true
)。可选扩展:
fallbackFormat
和后处理步骤的
transformPipeline
trim
,
parse_json
,
validate
,
coerce_types
)。无单独的
retry
对象——相关配置为
retryOnValidationFailure
+
maxRetries

Common Pitfalls

常见陷阱

  1. Overly broad instructions. Agents with vague instructions hallucinate more. Be specific about what the agent should and should not do.
  2. Too many tools per skill. Keep skills focused (3–8 tools). If a skill has 15+ tools, split it.
  3. Missing guardrails and approval gates. Define
    blockedTopics
    (plus the token / time budgets) in agent
    guardrails
    ; for destructive operations put a human in the loop with a gate that is actually enforced
    enableActionApproval: true
    (HITL queue, cloud) for auto-exposed actions,
    ai.requiresConfirmation
    on the action, or
    approval: 'always'
    on an MCP tool binding. AI metadata edits are already gated: they land as drafts a human must publish (ADR-0033). ⚠️
    requiresConfirmation
    on the tool was REMOVED (#3715, ADR-0033 §2) — it was read by no execution path, so it produced no pause.
    ToolSchema
    is strict, so authoring it now fails the parse with the migration attached. There is no
    requireApprovalFor
    field.
  4. Ignoring tool descriptions. The LLM uses tool
    description
    to decide when to call it. Poor descriptions = wrong tool selection.
  5. Not testing trigger phrases. Ambiguous trigger phrases cause skill conflicts. Test with edge-case inputs.
  6. Indexing everything. A knowledge source without a
    where
    filter and curated
    contentFields
    fills the index with drafts and boilerplate that pollute retrieval. Source hygiene is the metadata's job; relevance tuning (top-K, thresholds, reranking) belongs to the adapter.

  1. 指令过于宽泛。 指令模糊的Agent更容易产生幻觉。请明确说明Agent应该做什么和不应该做什么。
  2. 单个技能包含过多工具。 保持技能聚焦(3–8个工具)。若技能包含15个以上工具,请拆分。
  3. 缺少防护规则和审核 gate。 在Agent的
    guardrails
    中定义
    blockedTopics
    (以及token/时间预算);对于破坏性操作,设置实际生效的人工审核 gate——自动暴露的动作设置
    enableActionApproval: true
    (云版本人工审核队列),动作上设置
    ai.requiresConfirmation
    ,或MCP工具绑定上设置
    approval: 'always'
    。AI元数据编辑已默认受管控:它们会作为草稿保存,需人工发布(ADR-0033)。 ⚠️ 工具上的
    requiresConfirmation
    已被移除(#3715,ADR-0033 §2)——没有执行路径读取此字段,因此无法产生暂停效果。
    ToolSchema
    为严格模式,编写此字段会导致解析失败并附带迁移说明。无
    requireApprovalFor
    字段。
  4. 忽略工具描述。 LLM会根据工具的
    description
    判断何时调用它。描述不佳会导致工具选择错误。
  5. 未测试触发短语。 模糊的触发短语会导致技能冲突。请使用边缘案例输入进行测试。
  6. 索引所有内容。 未设置
    where
    过滤和精心选择
    contentFields
    的知识源会将草稿和模板内容填充到索引中,污染检索结果。源清理是元数据的职责;相关性调整(Top-K、阈值、重排序)属于适配器的工作。

App AI Blueprint (Skills + Tools + Knowledge)

应用AI蓝图(技能+工具+知识)

Reference layout for a scaffolded app:
LayerFilePattern
Reusable skill
src/skills/lead-qualification.skill.ts
defineSkill
— trigger phrases + trigger conditions + bounded toolset; pick a
surface
Tool metadata
src/tools/query-leads.tool.ts
defineTool
— JSON-Schema
parameters
; a discovery projection, not an executor (see caveat above)
Knowledge source
src/knowledge/sales-kb.ts
KnowledgeSourceSchema
metadata, registered at runtime via
IKnowledgeService.registerSource()
Central registration
defineStack({ skills: [...], tools: [...] })
agents
/
tools
/
skills
are the only AI stack collections — knowledge sources have none; agents are platform-supplied
Default for metadata apps: push business capability logic into skills, keep tools atomic, and wire domain knowledge through knowledge sources.

脚手架应用的参考布局:
层级文件模式
可复用技能
src/skills/lead-qualification.skill.ts
defineSkill
—— 触发短语 + 触发条件 + 限定工具集;选择
surface
工具元数据
src/tools/query-leads.tool.ts
defineTool
—— JSON-Schema
parameters
;仅用于发现投影,非执行器(详见上文提示)
知识源
src/knowledge/sales-kb.ts
KnowledgeSourceSchema
元数据,运行时通过
IKnowledgeService.registerSource()
注册
集中注册
defineStack({ skills: [...], tools: [...] })
agents
/
tools
/
skills
是唯一的AI栈集合——知识源无对应集合;Agent由平台提供
元数据应用的默认方案:将业务能力逻辑放入技能,保持工具原子化,并通过知识源连接领域知识。

Verify your work

验证您的工作

After authoring a
*.skill.ts
/
*.tool.ts
(or platform-internal
*.agent.ts
) or a model-registry entry, run the author-time gate before reporting done:
bash
os validate     # Zod schema + CEL predicate validation + bindings (no artifact)
编写完
*.skill.ts
/
*.tool.ts
(或平台内部的
*.agent.ts
)或模型注册表条目后,在完成前运行创作时验证:
bash
os validate     # Zod schema + CEL断言验证 + 绑定检查(不生成产物)

or: os build # the same gates, plus emits dist/

或:os build # 相同的检查,同时生成dist/


It confirms the agent/tool/model metadata conforms to the protocol and that any
CEL predicate (e.g. a tool's availability condition) parses and resolves. In a
scaffolded project the gate is `npm run validate`. See objectstack-platform →
**Verify your work**.

---

它会验证Agent/工具/模型元数据是否符合协议,以及任何CEL断言(如工具的可用条件)是否可解析和生效。在脚手架项目中,验证命令为`npm run validate`。详见objectstack-platform → **验证您的工作**章节。

---

References

参考资料

See references/_index.md for the full list of Zod schemas (with one-line descriptions) — pointers into
node_modules/@objectstack/spec/src/
. Always
Read
the source for exact field shapes; do not rely on memory of property names.
请查看references/_index.md获取完整的Zod schema列表(含单行描述)——指向
node_modules/@objectstack/spec/src/
中的代码。请始终查阅源代码以获取准确的字段结构;不要依赖对属性名称的记忆。