From c60c3100749baf34cee5f1247f45855504618155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 00:46:06 +0000 Subject: [PATCH] refactor: rename RoleDefinition fields for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - identity → goal - prepare → capabilities (string[]) - execute → procedure - report → output - outputSchema → meta Fixes #364 --- docs/architecture.md | 47 ++++++++----- docs/wf-stateless-design.md | 42 +++++++----- examples/analyze-topic.yaml | 15 +++-- examples/solve-issue.yaml | 37 +++++----- .../cli-workflow/src/__tests__/thread.test.ts | 10 +-- packages/cli-workflow/src/commands/thread.ts | 2 +- .../cli-workflow/src/commands/workflow.ts | 28 ++++---- packages/cli-workflow/src/validate.ts | 17 +++-- .../__tests__/build-role-prompt.test.ts | 67 ++++++++++++------- .../src/build-role-prompt.ts | 21 +++--- packages/workflow-agent-kit/src/run.ts | 8 +-- packages/workflow-protocol/src/schemas.ts | 12 ++-- packages/workflow-protocol/src/types.ts | 10 +-- 13 files changed, 187 insertions(+), 129 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 1900f4d..804d44b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -85,8 +85,13 @@ description: "End-to-end issue resolution" roles: planner: description: "Creates implementation plan" - systemPrompt: "You are a planning agent. Analyze the issue and create a step-by-step plan." - outputSchema: + goal: "You are a planning agent. Analyze the issue and create a step-by-step plan." + capabilities: + - issue-analysis + - planning + procedure: "Analyze the issue and create a detailed, actionable implementation plan." + output: "Output the plan summary and list of concrete steps." + meta: type: object properties: plan: { type: string } @@ -94,8 +99,13 @@ roles: required: [plan, steps] developer: description: "Implements code changes" - systemPrompt: "You are a developer agent. Implement the plan." - outputSchema: + goal: "You are a developer agent. Implement the plan." + capabilities: + - file-edit + - shell + procedure: "Implement the plan. Write code, tests, and ensure existing tests pass." + output: "List all files changed and provide a summary of the implementation." + meta: type: object properties: filesChanged: { type: array, items: { type: string } } @@ -103,8 +113,12 @@ roles: required: [filesChanged, summary] reviewer: description: "Reviews code changes" - systemPrompt: "You are a code reviewer. Review the implementation." - outputSchema: + goal: "You are a code reviewer. Review the implementation." + capabilities: + - code-review + procedure: "Review the implementation against the plan." + output: "Approve or reject with detailed comments." + meta: type: object properties: approved: { type: boolean } @@ -133,7 +147,7 @@ graph: Key properties: -- **`roles`** — inline role definitions; each `outputSchema` is a JSON Schema (stored as its own CAS node on registration) +- **`roles`** — inline role definitions; each `meta` is a JSON Schema (stored as its own CAS node on registration) - **`conditions`** — named JSONata expressions evaluated against the `ModeratorContext` - **`graph`** — `Record` — first matching transition wins; `condition: null` = fallback - **No agent binding** — agent selection is a deployment concern, configured in `config.yaml` @@ -156,7 +170,7 @@ Each `uwf thread step` runs exactly one cycle: moderator → agent → extract. │ Output: raw string (frontmatter markdown) │ │ Phase 3: EXTRACT -│ Input: raw agent output + role's outputSchema +│ Input: raw agent output + role's meta schema │ Engine: two-layer extract (frontmatter fast path → LLM fallback) │ Output: CasRef to structured output node │ @@ -213,7 +227,7 @@ Contract: - Parses argv - Loads `.env` from storage root - Builds `AgentContext` by walking the CAS chain from `threads.yaml` head - - Resolves the role's `outputSchema` and builds `outputFormatInstruction` + - Resolves the role's `meta` schema and builds `outputFormatInstruction` - Calls the agent's `run` function - Runs two-layer extract on the raw output - Writes `StepNode` to CAS (output + detail + prev link) @@ -242,7 +256,7 @@ scope: role Fixed the login redirect by updating the auth middleware... ``` -The `outputFormatInstruction` (built by `buildOutputFormatInstruction` in `workflow-agent-kit`) is prepended to the role's system prompt, so the deliverable format is the first thing the agent sees. It lists the expected frontmatter fields derived from the role's JSON Schema. +The `outputFormatInstruction` (built by `buildOutputFormatInstruction` in `workflow-agent-kit`) is prepended to the role's system prompt, so the deliverable format is the first thing the agent sees. It lists the expected frontmatter fields derived from the role's `meta` JSON Schema. ## Two-layer extract @@ -253,7 +267,7 @@ Structured output extraction uses a two-layer strategy (`workflow-agent-kit`): 1. Parse YAML frontmatter from raw agent output (`parseFrontmatterMarkdown`) 2. Validate required fields (`validateFrontmatter`) 3. Build a candidate object from frontmatter fields (`status`, `next`, `confidence`, `artifacts`, `scope`) -4. `store.put()` the candidate against the role's `outputSchema` +4. `store.put()` the candidate against the role's `meta` schema 5. Validate with `json-cas` schema validation 6. If valid → return `outputHash` (zero LLM cost) @@ -272,7 +286,7 @@ If the fast path returns `null` (no frontmatter, invalid, or doesn't satisfy sch `workflow-agent-kit` prepends two pieces of context to the agent's system prompt: -1. **Deliverable format instruction** — generated from the role's `outputSchema`, tells the agent exactly what frontmatter fields to produce and the expected format +1. **Deliverable format instruction** — generated from the role's `meta` schema, tells the agent exactly what frontmatter fields to produce and the expected format 2. **Scope constraint** — "Focus exclusively on YOUR role's deliverable. Do not perform actions outside your role's scope." This ensures agents produce parseable frontmatter output without requiring per-agent format knowledge. @@ -289,8 +303,11 @@ payload: roles: planner: description: "Creates implementation plan" - systemPrompt: "You are a planning agent..." - outputSchema: "5GWKR8TN1V3JA" # cas_ref → JSON Schema node + goal: "You are a planning agent..." + capabilities: [planning, issue-analysis] + procedure: "Analyze the issue and create a plan." + output: "Output the plan summary." + meta: "5GWKR8TN1V3JA" # cas_ref → JSON Schema node conditions: notApproved: description: "Reviewer rejected" @@ -318,7 +335,7 @@ payload: start: "4TNVW8KR2B3MA" # cas_ref → StartNode prev: "2MXBG6PN4A8JR" # cas_ref → previous StepNode (null for first step) role: "developer" - output: "9KRVW3TN5F1QA" # cas_ref → structured output (validated against outputSchema) + output: "9KRVW3TN5F1QA" # cas_ref → structured output (validated against meta schema) detail: "7BQST3VW9F2MA" # cas_ref → execution detail (raw turns, session data) agent: "uwf-hermes" # agent command used (plain string) ``` diff --git a/docs/wf-stateless-design.md b/docs/wf-stateless-design.md index 1bddb8f..f92768e 100644 --- a/docs/wf-stateless-design.md +++ b/docs/wf-stateless-design.md @@ -112,8 +112,8 @@ uwf-hermes **约定:** - `uwf step` 负责 moderator 决策,将 role 传给 agent CLI -- agent-kit 根据 thread + role 从 CAS 读 systemPrompt / outputSchema -- agent-kit 组装完整 prompt(role systemPrompt + thread context + user prompt from StartNode) +- agent-kit 根据 thread + role 从 CAS 读 goal / capabilities / procedure / output / meta +- agent-kit 组装完整 prompt(role goal/capabilities/procedure/output + thread context + user prompt from StartNode) - agent 执行实际逻辑,agent-kit 负责 extract - agent 将 StepNode 写入 CAS(含 output、detail、agent、prev),但**不挪链头指针** - stdout 输出新 StepNode 的 CAS hash(纯文本,一行) @@ -143,7 +143,7 @@ uwf-hermes #### `Workflow` -Roles 和 moderator 内联在 Workflow 中,只有 outputSchema 独立为 CAS 节点(方便 json-cas 校验)。 +Roles 和 moderator 内联在 Workflow 中,只有 meta 独立为 CAS 节点(方便 json-cas 校验)。 ```yaml type: @@ -153,16 +153,25 @@ payload: roles: planner: description: "Creates implementation plan" - systemPrompt: "You are a planning agent..." - outputSchema: "5GWKR8TN1V3JA" # cas_ref → JSON Schema 节点(json-cas 内置) + goal: "You are a planning agent..." + capabilities: [planning, issue-analysis] + procedure: "Analyze the issue and create a plan." + output: "Output the plan summary." + meta: "5GWKR8TN1V3JA" # cas_ref → JSON Schema 节点(json-cas 内置) developer: description: "Implements code changes" - systemPrompt: "You are a developer agent..." - outputSchema: "8CNWT4KR6D1HV" # cas_ref → JSON Schema 节点 + goal: "You are a developer agent..." + capabilities: [file-edit, shell] + procedure: "Implement the plan." + output: "List all files changed." + meta: "8CNWT4KR6D1HV" # cas_ref → JSON Schema 节点 reviewer: description: "Reviews code changes" - systemPrompt: "You are a code reviewer..." - outputSchema: "1VPBG9SM5E7WK" # cas_ref → JSON Schema 节点 + goal: "You are a code reviewer..." + capabilities: [code-review] + procedure: "Review the implementation." + output: "Approve or reject with comments." + meta: "1VPBG9SM5E7WK" # cas_ref → JSON Schema 节点 conditions: needsClarification: description: "Planner requests clarification from user" @@ -189,7 +198,7 @@ payload: condition: null ``` -- `roles` — 内联定义,每个 role 的 `outputSchema` 是独立的 cas_ref(指向 json-cas 内置 JSON Schema 节点) +- `roles` — 内联定义,每个 role 的 `meta` 是独立的 cas_ref(指向 json-cas 内置 JSON Schema 节点) - `conditions` — `Record`,命名条件,方便画图描述 - `graph` — `Record`,每个 Transition = `{ role, condition }` - `condition` 引用 conditions 中的 key,`null` = fallback @@ -234,14 +243,14 @@ payload: start: "4TNVW8KR2B3MA" # cas_ref → StartNode(每个 step 都引用) prev: "2MXBG6PN4A8JR" # cas_ref → 前一个 StepNode,第一步为 null role: "developer" - output: "9KRVW3TN5F1QA" # cas_ref → 结构化输出节点(符合 role 的 outputSchema) + output: "9KRVW3TN5F1QA" # cas_ref → 结构化输出节点(符合 role 的 meta schema) detail: "7BQST3VW9F2MA" # cas_ref → 执行详情(content node / 子 workflow terminal StepNode / ...) agent: "uwf-cursor" # 实际使用的 agent 命令(纯字符串) ``` - `start` — 每个 StepNode 都直接引用 StartNode,方便随机访问 - `prev` — 前一个 StepNode 的 cas_ref,第一步为 `null`(不指向 StartNode) -- `output` — cas_ref,指向符合 role outputSchema 的 CAS 节点,可用 json-cas 校验 +- `output` — cas_ref,指向符合 role meta schema 的 CAS 节点,可用 json-cas 校验 - `detail` — cas_ref,指向执行详情。可以是原始 agent 输出(content node),也可以是子 workflow thread 的 terminal StepNode(workflowAsAgent 场景) - `agent` — 纯字符串,不是 CAS 节点 @@ -372,7 +381,7 @@ type ThreadId = string; /** 一个 step 的核心数据,被 StepNode payload 和 JSONata 上下文共享 */ type StepRecord = { role: string; - output: CasRef; // cas_ref → 结构化输出节点(符合 role outputSchema) + output: CasRef; // cas_ref → 结构化输出节点(符合 role meta schema) detail: CasRef; // cas_ref → 执行详情(content node / 子 workflow terminal StepNode) agent: string; // 实际使用的 agent 命令(纯字符串) }; @@ -383,8 +392,11 @@ type StepRecord = { ```typescript type RoleDefinition = { description: string; - systemPrompt: string; - outputSchema: CasRef; // cas_ref → json-cas 内置 JSON Schema 节点 + goal: string; + capabilities: string[]; + procedure: string; + output: string; + meta: CasRef; // cas_ref → json-cas 内置 JSON Schema 节点 }; type Transition = { diff --git a/examples/analyze-topic.yaml b/examples/analyze-topic.yaml index 7f0b9e6..585b32b 100644 --- a/examples/analyze-topic.yaml +++ b/examples/analyze-topic.yaml @@ -3,22 +3,23 @@ description: "Single-role topic analysis using four-phase role description" roles: analyst: description: "Analyzes a given topic and produces a structured summary" - identity: | + goal: | You are a research analyst with expertise in breaking down complex topics into clear, structured summaries. You think critically and cite key points. - prepare: | - Review the topic carefully. Consider multiple perspectives and identify - the core question being asked. - execute: | + capabilities: + - research + - critical-thinking + - structured-writing + procedure: | Analyze the topic by: 1. Identifying the main thesis or question 2. Listing 3-5 key points with brief explanations 3. Noting any counterarguments or caveats Keep your analysis concise (under 500 words). - report: | + output: | Provide your analysis as markdown under the frontmatter. The frontmatter must include your structured findings. - outputSchema: + meta: type: object properties: thesis: diff --git a/examples/solve-issue.yaml b/examples/solve-issue.yaml index 2f86083..34302ac 100644 --- a/examples/solve-issue.yaml +++ b/examples/solve-issue.yaml @@ -3,11 +3,13 @@ description: "End-to-end issue resolution" roles: planner: description: "Creates implementation plan" - identity: "You are a planning agent. You analyze issues and create step-by-step plans." - prepare: "Read the issue description and any linked context carefully." - execute: "Analyze the issue and create a detailed, actionable implementation plan." - report: "Output the plan summary and list of concrete steps." - outputSchema: + goal: "You are a planning agent. You analyze issues and create step-by-step plans." + capabilities: + - issue-analysis + - planning + procedure: "Analyze the issue and create a detailed, actionable implementation plan." + output: "Output the plan summary and list of concrete steps." + meta: type: object properties: plan: @@ -19,11 +21,14 @@ roles: required: [plan, steps] developer: description: "Implements code changes" - identity: "You are a developer agent. You implement code changes according to plans." - prepare: "Load coding tools and review the project structure and conventions." - execute: "Implement the plan. Write code, tests, and ensure existing tests pass." - report: "List all files changed and provide a summary of the implementation." - outputSchema: + goal: "You are a developer agent. You implement code changes according to plans." + capabilities: + - file-edit + - shell + - testing + procedure: "Implement the plan. Write code, tests, and ensure existing tests pass." + output: "List all files changed and provide a summary of the implementation." + meta: type: object properties: filesChanged: @@ -35,11 +40,13 @@ roles: required: [filesChanged, summary] reviewer: description: "Reviews code changes" - identity: "You are a code reviewer. You review implementations for correctness and quality." - prepare: "Review the project's coding standards and conventions." - execute: "Review the implementation against the plan. Check for bugs, edge cases, and style." - report: "Approve or reject with detailed comments explaining your decision." - outputSchema: + goal: "You are a code reviewer. You review implementations for correctness and quality." + capabilities: + - code-review + - static-analysis + procedure: "Review the implementation against the plan. Check for bugs, edge cases, and style." + output: "Approve or reject with detailed comments explaining your decision." + meta: type: object properties: approved: diff --git a/packages/cli-workflow/src/__tests__/thread.test.ts b/packages/cli-workflow/src/__tests__/thread.test.ts index fb83981..721750e 100644 --- a/packages/cli-workflow/src/__tests__/thread.test.ts +++ b/packages/cli-workflow/src/__tests__/thread.test.ts @@ -211,11 +211,11 @@ describe("cmdThreadRead ### Content section", () => { roles: { writer: { description: "Write", - identity: "You are a writer.", - prepare: "", - execute: "Write content as requested.", - report: "Summarize what was written.", - outputSchema: "placeholder00" as CasRef, + goal: "You are a writer.", + capabilities: [], + procedure: "Write content as requested.", + output: "Summarize what was written.", + meta: "placeholder00" as CasRef, }, }, conditions: {}, diff --git a/packages/cli-workflow/src/commands/thread.ts b/packages/cli-workflow/src/commands/thread.ts index 0cc89dc..dde7a64 100644 --- a/packages/cli-workflow/src/commands/thread.ts +++ b/packages/cli-workflow/src/commands/thread.ts @@ -500,7 +500,7 @@ function formatThreadReadMarkdown(options: { ]; const roleDef = workflow.roles[item.payload.role]; if (roleDef) { - const prompt = roleDef.identity; + const prompt = roleDef.goal; stepLines.push("", "### Prompt", "", prompt); } if (item.payload.detail) { diff --git a/packages/cli-workflow/src/commands/workflow.ts b/packages/cli-workflow/src/commands/workflow.ts index 32c1b93..56a9377 100644 --- a/packages/cli-workflow/src/commands/workflow.ts +++ b/packages/cli-workflow/src/commands/workflow.ts @@ -42,17 +42,17 @@ function isJsonSchema(value: unknown): value is JSONSchema { return typeof value === "object" && value !== null && !Array.isArray(value); } -async function resolveOutputSchemaRef( +async function resolveMetaRef( uwf: UwfStore, roleName: string, - outputSchema: unknown, + meta: unknown, ): Promise { - if (!isJsonSchema(outputSchema)) { - fail(`role "${roleName}": outputSchema must be a JSON Schema object`); + if (!isJsonSchema(meta)) { + fail(`role "${roleName}": meta must be a JSON Schema object`); } - const schema: JSONSchema = outputSchema.title === undefined - ? { ...outputSchema, title: roleName } - : outputSchema; + const schema: JSONSchema = meta.title === undefined + ? { ...meta, title: roleName } + : meta; return putSchema(uwf.store, schema); } @@ -62,18 +62,18 @@ async function materializeWorkflowPayload( ): Promise { const roles: Record = {}; for (const [roleName, role] of Object.entries(raw.roles)) { - const outputSchema = await resolveOutputSchemaRef( + const meta = await resolveMetaRef( uwf, `${raw.name}.${roleName}`, - role.outputSchema, + role.meta, ); roles[roleName] = { description: role.description, - identity: role.identity, - prepare: role.prepare, - execute: role.execute, - report: role.report, - outputSchema, + goal: role.goal, + capabilities: role.capabilities, + procedure: role.procedure, + output: role.output, + meta, }; } return { diff --git a/packages/cli-workflow/src/validate.ts b/packages/cli-workflow/src/validate.ts index 8c50db2..a82032c 100644 --- a/packages/cli-workflow/src/validate.ts +++ b/packages/cli-workflow/src/validate.ts @@ -14,15 +14,18 @@ function isRoleDefinition(value: unknown): boolean { if (!isRecord(value)) { return false; } - const outputSchema = value.outputSchema; - const schemaOk = isRecord(outputSchema) && typeof outputSchema.type === "string"; + const meta = value.meta; + const metaOk = isRecord(meta) && typeof meta.type === "string"; + const capabilities = value.capabilities; + const capabilitiesOk = + Array.isArray(capabilities) && capabilities.every((c) => typeof c === "string"); return ( typeof value.description === "string" && - typeof value.identity === "string" && - typeof value.prepare === "string" && - typeof value.execute === "string" && - typeof value.report === "string" && - schemaOk + typeof value.goal === "string" && + capabilitiesOk && + typeof value.procedure === "string" && + typeof value.output === "string" && + metaOk ); } diff --git a/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts b/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts index 4ce456a..4965cc4 100644 --- a/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts +++ b/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts @@ -1,54 +1,71 @@ -import { describe, expect, test } from "vitest"; import type { RoleDefinition } from "@uncaged/workflow-protocol"; +import { describe, expect, test } from "vitest"; import { buildRolePrompt } from "../src/build-role-prompt.js"; describe("buildRolePrompt", () => { test("all fields present", () => { const role: RoleDefinition = { description: "A coder", - identity: "You are a senior developer.", - prepare: "Load cursor-agent skill.", - execute: "Implement the feature.", - report: "Summarize changes.", - outputSchema: "placeholder00000" as string, + goal: "You are a senior developer.", + capabilities: ["cursor-agent", "file-edit"], + procedure: "Implement the feature.", + output: "Summarize changes.", + meta: "placeholder00000" as string, }; const result = buildRolePrompt(role); - expect(result).toContain("## Identity"); + expect(result).toContain("## Goal"); expect(result).toContain("You are a senior developer."); - expect(result).toContain("## Prepare"); - expect(result).toContain("Load cursor-agent skill."); - expect(result).toContain("## Execute"); + expect(result).toContain("## Capabilities"); + expect(result).toContain("- cursor-agent"); + expect(result).toContain("- file-edit"); + expect(result).toContain("## Procedure"); expect(result).toContain("Implement the feature."); - expect(result).toContain("## Report"); + expect(result).toContain("## Output"); expect(result).toContain("Summarize changes."); }); test("empty fields are omitted", () => { const role: RoleDefinition = { description: "A reviewer", - identity: "You are a code reviewer.", - prepare: "", - execute: "Review the PR diff carefully.", - report: "", - outputSchema: "placeholder00000" as string, + goal: "You are a code reviewer.", + capabilities: [], + procedure: "Review the PR diff carefully.", + output: "", + meta: "placeholder00000" as string, }; const result = buildRolePrompt(role); - expect(result).toContain("## Identity"); - expect(result).toContain("## Execute"); - expect(result).not.toContain("## Prepare"); - expect(result).not.toContain("## Report"); + expect(result).toContain("## Goal"); + expect(result).toContain("## Procedure"); + expect(result).not.toContain("## Capabilities"); + expect(result).not.toContain("## Output"); }); test("all empty returns empty string", () => { const role: RoleDefinition = { description: "Minimal", - identity: "", - prepare: "", - execute: "", - report: "", - outputSchema: "placeholder00000" as string, + goal: "", + capabilities: [], + procedure: "", + output: "", + meta: "placeholder00000" as string, }; const result = buildRolePrompt(role); expect(result).toBe(""); }); + + test("capabilities rendered as bullet list", () => { + const role: RoleDefinition = { + description: "Agent", + goal: "", + capabilities: ["search", "code", "browse"], + procedure: "", + output: "", + meta: "placeholder00000" as string, + }; + const result = buildRolePrompt(role); + expect(result).toContain("## Capabilities"); + expect(result).toContain("- search"); + expect(result).toContain("- code"); + expect(result).toContain("- browse"); + }); }); diff --git a/packages/workflow-agent-kit/src/build-role-prompt.ts b/packages/workflow-agent-kit/src/build-role-prompt.ts index 9530766..199d4a3 100644 --- a/packages/workflow-agent-kit/src/build-role-prompt.ts +++ b/packages/workflow-agent-kit/src/build-role-prompt.ts @@ -3,26 +3,27 @@ import type { RoleDefinition } from "@uncaged/workflow-protocol"; /** * Build the role prompt from a RoleDefinition. * - * Assembles structured sections: Identity, Prepare, Execute, Report. - * Empty strings are omitted from the output. + * Assembles structured sections: Goal, Capabilities, Procedure, Output. + * Empty strings and empty arrays are omitted from the output. */ export function buildRolePrompt(role: RoleDefinition): string { const sections: string[] = []; - if (role.identity !== "") { - sections.push(`## Identity\n\n${role.identity}`); + if (role.goal !== "") { + sections.push(`## Goal\n\n${role.goal}`); } - if (role.prepare !== "") { - sections.push(`## Prepare\n\n${role.prepare}`); + if (role.capabilities.length > 0) { + const list = role.capabilities.map((c) => `- ${c}`).join("\n"); + sections.push(`## Capabilities\n\n${list}`); } - if (role.execute !== "") { - sections.push(`## Execute\n\n${role.execute}`); + if (role.procedure !== "") { + sections.push(`## Procedure\n\n${role.procedure}`); } - if (role.report !== "") { - sections.push(`## Report\n\n${role.report}`); + if (role.output !== "") { + sections.push(`## Output\n\n${role.output}`); } return sections.join("\n\n"); diff --git a/packages/workflow-agent-kit/src/run.ts b/packages/workflow-agent-kit/src/run.ts index 75e87b8..70b3c64 100644 --- a/packages/workflow-agent-kit/src/run.ts +++ b/packages/workflow-agent-kit/src/run.ts @@ -131,13 +131,13 @@ export function createAgent(options: AgentOptions): () => Promise { fail(`unknown role: ${role}`); } - const outputSchema = getSchema(ctx.meta.store, roleDef.outputSchema); - if (outputSchema !== null) { - ctx.outputFormatInstruction = buildOutputFormatInstruction(outputSchema); + const metaSchema = getSchema(ctx.meta.store, roleDef.meta); + if (metaSchema !== null) { + ctx.outputFormatInstruction = buildOutputFormatInstruction(metaSchema); } const agentResult = await runAgent(options, ctx); - const outputHash = await extractOutput(agentResult.output, roleDef.outputSchema, storageRoot, ctx); + const outputHash = await extractOutput(agentResult.output, roleDef.meta, storageRoot, ctx); const stepHash = await persistStep({ ctx, outputHash, diff --git a/packages/workflow-protocol/src/schemas.ts b/packages/workflow-protocol/src/schemas.ts index a4e9c58..fd85793 100644 --- a/packages/workflow-protocol/src/schemas.ts +++ b/packages/workflow-protocol/src/schemas.ts @@ -2,14 +2,14 @@ import type { JSONSchema } from "@uncaged/json-cas"; const ROLE_DEFINITION: JSONSchema = { type: "object", - required: ["description", "identity", "prepare", "execute", "report", "outputSchema"], + required: ["description", "goal", "capabilities", "procedure", "output", "meta"], properties: { description: { type: "string" }, - identity: { type: "string" }, - prepare: { type: "string" }, - execute: { type: "string" }, - report: { type: "string" }, - outputSchema: { type: "string", format: "cas_ref" }, + goal: { type: "string" }, + capabilities: { type: "array", items: { type: "string" } }, + procedure: { type: "string" }, + output: { type: "string" }, + meta: { type: "string", format: "cas_ref" }, }, additionalProperties: false, }; diff --git a/packages/workflow-protocol/src/types.ts b/packages/workflow-protocol/src/types.ts index 6d57bc7..4f063eb 100644 --- a/packages/workflow-protocol/src/types.ts +++ b/packages/workflow-protocol/src/types.ts @@ -18,11 +18,11 @@ export type StepRecord = { export type RoleDefinition = { description: string; - identity: string; - prepare: string; - execute: string; - report: string; - outputSchema: CasRef; + goal: string; + capabilities: string[]; + procedure: string; + output: string; + meta: CasRef; }; export type Transition = {