Knowledge Documents

workflow.listKnowledgeDocuments()workflow.getKnowledgeDocument()workflow.createKnowledgeDocument()workflow.editKnowledgeDocument()workflow.deleteKnowledgeDocument()workflow.searchKnowledgeDocuments() 是 issue #86 引入的项目知识库 helper。它们把文档索引和正文写入 context.persistentValue.workflow,因此数据只通过 server 数据库存储,不会落到 CLI/App 本地 KV。CLI/App 本地运行在已配置 WORKFLOW_SERVER_URL / WORKFLOW_SERVER_ADMIN_KEY,或已保存 workspace CLI workflow-auth.json,或 App 已绑定 server 时也可以使用这些 helper;未连接时才会报错。

签名

workflow.listKnowledgeDocuments(context: WorkflowContext): Promise<WorkflowKnowledgeDocumentSummary[]>

workflow.getKnowledgeDocument(
  context: WorkflowContext,
  documentId: string,
): Promise<WorkflowKnowledgeDocument | undefined>

workflow.createKnowledgeDocument(
  context: WorkflowContext,
  input: { id?: string; title: string; markdown: string },
): Promise<WorkflowKnowledgeDocument>

workflow.editKnowledgeDocument(
  context: WorkflowContext,
  input: { id: string; title?: string; markdown?: string },
): Promise<WorkflowKnowledgeDocument>

workflow.deleteKnowledgeDocument(
  context: WorkflowContext,
  documentId: string,
): Promise<{ id: string; deleted: boolean }>

workflow.searchKnowledgeDocuments(
  context: WorkflowContext,
  input: {
    query: string;
    documentId?: string;
    beforeLines?: number;
    afterLines?: number;
    maxMatches?: number;
    pageSize?: number;
    cursor?: string;
  },
): Promise<WorkflowKnowledgeSearchResult>

workflow.readKnowledgeDocumentLines(
  context: WorkflowContext,
  input: {
    documentId: string;
    startLine: number;
    endLine: number;
  },
): Promise<WorkflowKnowledgeDocumentLinesResult>

数据结构

interface WorkflowKnowledgeDocument {
  id: string;
  title: string;
  markdown: string;
  createdAt: string;
  updatedAt: string;
}

interface WorkflowKnowledgeDocumentSummary {
  id: string;
  title: string;
  markdownPreview: string;
  createdAt: string;
  updatedAt: string;
}

interface WorkflowKnowledgeSearchResult {
  query: string;
  documentsSearched: number;
  totalMatches: number;
  matchesTruncated: boolean;
  maxMatches: number;
  pageSize: number;
  cursor?: string;
  nextCursor?: string;
  hasMore: boolean;
  matches: Array<{
    documentId: string;
    title: string;
    lineNumber: number;
    line: string;
    before: Array<{ lineNumber: number; content: string }>;
    after: Array<{ lineNumber: number; content: string }>;
  }>;
}

interface WorkflowKnowledgeDocumentLinesResult {
  documentId: string;
  title: string;
  startLine: number;
  endLine: number;
  totalLines: number;
  lines: Array<{ lineNumber: number; content: string }>;
}

存储语义

知识库复用现有 PostgreSQL workflow_kv_entries 表,不新增表:
scopekey内容
workflowknowledge.documents文档索引和摘要。
workflowknowledge.document.<id>单篇文档正文,固定包含 markdown 字段。
删除文档会从 knowledge.documents 索引中移除,并把单篇文档 key 写成 tombstone 标记。当前 KV/PersistentValue 还没有 delete primitive,因此 tombstone 用于保留审计痕迹。

搜索

searchKnowledgeDocuments() 按 markdown 行搜索。documentId 省略时查找全部文档;传入时只查找指定文档。beforeLinesafterLines 控制每条匹配向上、向下返回多少行上下文,取值范围是 0 到 50。pageSize 控制本页最多返回多少条匹配,默认 200,最大 1000;cursor 使用上一页返回的 nextCursortotalMatches 仍记录实际命中总数,hasMore / nextCursor 表示是否还有下一页。maxMatches 是旧参数,未传 pageSize 时仍作为本页大小兼容。
const result = await workflow.searchKnowledgeDocuments(context, {
  query: "PersistentValue",
  beforeLines: 1,
  afterLines: 1,
  pageSize: 200,
});

for (const match of result.matches) {
  console.log(match.title, match.lineNumber, match.line);
}
readKnowledgeDocumentLines() 用于指定文档的行范围读取,startLine / endLine 是 1-based inclusive。单次最多读取 1000 行;超出文档总行数时会把 endLine 截到实际末行,startLine 超出总行数时返回空 lines
const excerpt = await workflow.readKnowledgeDocumentLines(context, {
  documentId: "runbook",
  startLine: 120,
  endLine: 160,
});

错误

情况结果
本地 CLI/App 未连接 server 且未注入 PersistentValue store调用时抛出 WorkflowError,不会写入本地 KV。
id 非法抛出 WorkflowError;id 必须以字母或数字开头,只能包含字母、数字、点、下划线和横线。
title 为空抛出 WorkflowError
query 为空抛出 WorkflowError
pageSize / maxMatches 超出 1 到 1000抛出 WorkflowError
startLine / endLine 非法或单次超过 1000 行抛出 WorkflowError
新建已存在文档抛出 WorkflowError;server 管理 API 映射为 409。
编辑或搜索不存在的文档抛出 WorkflowError;server 管理 API 映射为 404。

示例

export const workflowWithKnowledge = workflow.defineWorkflow<Input, OutputPayload>({
  name: "knowledge-demo",
  async run(input, context) {
    const document = await workflow.createKnowledgeDocument(context, {
      title: input.title,
      markdown: input.markdown,
    });

    const search = await workflow.searchKnowledgeDocuments(context, {
      documentId: document.id,
      query: input.query,
      beforeLines: 2,
      afterLines: 2,
    });

    return workflow.createOutputPayload({
      items: [
        workflow.createOutputItem({
          title: "Knowledge search",
          contentType: "json",
          content: search,
        }),
      ],
    });
  },
});

Conversation 示例

workspace/workflow/conversation-knowledge 展示了 issue #86 第三阶段的 conversation 应用模式:一个 conversation id 对应一篇知识库文档,每轮消息都先写入 context.conversation,再把完整 transcript 通过 workflow.createKnowledgeDocument() / workflow.editKnowledgeDocument() 同步到 PersistentValue-backed 知识库。 本地调试使用 dry-run,只生成预览 markdown:
workflow-code json workspace/workflow/conversation-knowledge \
  --conversation-id demo-thread \
  -- --dry-run --message "记录今天的结论" --title "Demo conversation"
真实写入需要 server 数据库持久值,例如调用 server run API:
curl -X POST "$WORKFLOW_SERVER_URL/api/workflows/conversation-knowledge/run" \
  -H "Authorization: Bearer $WORKFLOW_SERVER_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "draft",
    "conversation_id": "demo-thread",
    "args": ["--message", "记录今天的结论", "--title", "Demo conversation"]
  }'

追踪

本文档由 issue #86 记录。API 对齐 core/knowledge/index.tscore/runtime-api.ts