From 463d010c24970cc0bcf8e2b9f4a82da1ae33e475 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 18:44:09 +0800 Subject: [PATCH 1/6] feat(agent): add instructions api --- packages/page-agent/src/PageAgent.ts | 31 +++++++++++++++++++++++++ packages/page-agent/src/config/index.ts | 18 ++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/packages/page-agent/src/PageAgent.ts b/packages/page-agent/src/PageAgent.ts index 36fb27e..1390b29 100644 --- a/packages/page-agent/src/PageAgent.ts +++ b/packages/page-agent/src/PageAgent.ts @@ -361,9 +361,40 @@ export class PageAgent extends EventTarget { return systemPrompt } + /** + * Get instructions from config and format as XML block + */ + async #getInstructions(): Promise { + const { instructions } = this.config + if (!instructions) return '' + + const systemInstructions = instructions.system?.trim() + const url = await this.pageController.getCurrentUrl() + const pageInstructions = instructions.getPageInstructions?.(url)?.trim() + + if (!systemInstructions && !pageInstructions) return '' + + let result = '\n' + + if (systemInstructions) { + result += `\n${systemInstructions}\n\n` + } + + if (pageInstructions) { + result += `\n${pageInstructions}\n\n` + } + + result += '\n\n' + + return result + } + async #assembleUserPrompt(): Promise { let prompt = '' + // (optional) + prompt += await this.#getInstructions() + // // - // - diff --git a/packages/page-agent/src/config/index.ts b/packages/page-agent/src/config/index.ts index f5a44e6..b53da7d 100644 --- a/packages/page-agent/src/config/index.ts +++ b/packages/page-agent/src/config/index.ts @@ -42,6 +42,24 @@ export interface AgentConfig { */ customTools?: Record + /** + * Instructions to guide the agent's behavior + */ + instructions?: { + /** + * Global system-level instructions, applied to all tasks + */ + system?: string + + /** + * Dynamic page-level instructions callback + * Called before each step to get instructions for the current page + * @param url - Current page URL (window.location.href) + * @returns Instructions string, or undefined/null to skip + */ + getPageInstructions?: (url: string) => string | undefined | null + } + // lifecycle hooks // @todo: use event instead of hooks From c3c01b63fb0206f563f0be2fb87d5005ecae30ef Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:02:18 +0800 Subject: [PATCH 2/6] docs: upgrade docs for custom instructions --- .../website/src/components/DocsLayout.tsx | 2 +- .../src/docs/features/instructions/page.tsx | 135 +++++++++++++++ .../features/knowledge-injection/page.tsx | 162 ------------------ .../website/src/i18n/locales/en-US/common.ts | 2 +- .../website/src/i18n/locales/zh-CN/common.ts | 2 +- packages/website/src/router.tsx | 6 +- 6 files changed, 141 insertions(+), 168 deletions(-) create mode 100644 packages/website/src/docs/features/instructions/page.tsx delete mode 100644 packages/website/src/docs/features/knowledge-injection/page.tsx diff --git a/packages/website/src/components/DocsLayout.tsx b/packages/website/src/components/DocsLayout.tsx index 944edc7..11064f7 100644 --- a/packages/website/src/components/DocsLayout.tsx +++ b/packages/website/src/components/DocsLayout.tsx @@ -34,7 +34,7 @@ export default function DocsLayout({ children }: DocsLayoutProps) { items: [ { title: t('nav.model_integration'), path: '/docs/features/model-integration' }, { title: t('nav.custom_tools'), path: '/docs/features/custom-tools' }, - { title: t('nav.knowledge_injection'), path: '/docs/features/knowledge-injection' }, + { title: t('nav.knowledge_injection'), path: '/docs/features/instructions' }, { title: t('nav.security_permissions'), path: '/docs/features/security-permissions' }, { title: t('nav.data_masking'), path: '/docs/features/data-masking' }, ], diff --git a/packages/website/src/docs/features/instructions/page.tsx b/packages/website/src/docs/features/instructions/page.tsx new file mode 100644 index 0000000..6689672 --- /dev/null +++ b/packages/website/src/docs/features/instructions/page.tsx @@ -0,0 +1,135 @@ +import { useTranslation } from 'react-i18next' + +import CodeEditor from '@/components/CodeEditor' + +export default function KnowledgeInjection() { + const { i18n } = useTranslation() + const isZh = i18n.language === 'zh-CN' + + return ( +
+

{isZh ? '知识注入' : 'Instructions'}

+ +

+ {isZh + ? '通过 instructions 配置,为 AI 注入系统级指导和页面级上下文,让它更好地理解你的业务场景。' + : 'Use the instructions config to inject system-level directives and page-specific context, helping the AI better understand your application.'} +

+ + {/* System Instructions */} +
+

+ {isZh ? '系统级指导 (System Instructions)' : 'System Instructions'} +

+ +

+ {isZh + ? '全局提示词,应用于所有任务。定义 AI 的角色、工作风格和行为边界。' + : "Global directives applied to all tasks. Define the AI's role, working style, and behavioral boundaries."} +

+ + +
+ + {/* Page Instructions */} +
+

+ {isZh ? '页面级指导 (Page Instructions)' : 'Page Instructions'} +

+ +

+ {isZh + ? '动态回调函数,在每个 step 执行前调用,根据当前页面 URL 返回特定提示词。适用于为不同页面提供针对性的操作引导。' + : 'A dynamic callback invoked before each step. Returns page-specific instructions based on the current URL. Useful for providing targeted guidance on different pages.'} +

+ + { + if (url.includes('/checkout')) { + return \` +This is the checkout page. +- Verify shipping address before proceeding +- Check if any discounts are applied +- Confirm the total amount with the user +\` + } + + if (url.includes('/products')) { + return \` +This is the product listing page. +- Use filters to narrow down search results +- Check stock availability before adding to cart +\` + } + + return undefined // No special instructions for other pages + } + } +})`} + /> +
+ + {/* How It Works */} +
+

{isZh ? '工作原理' : 'How It Works'}

+ +

+ {isZh + ? '在每个执行步骤之前,page-agent 会将 instructions 拼接到用户提示词中:' + : 'Before each execution step, page-agent prepends the instructions to the user prompt:'} +

+ + + +You are a professional e-commerce assistant. +... + + +This is the checkout page. +... + + + +`} + /> + +
    +
  • + {isZh + ? '如果 system 为空,则不输出 标签' + : 'If system is empty, the tag is omitted'} +
  • +
  • + {isZh + ? '如果 getPageInstructions 返回空值,则不输出 标签' + : 'If getPageInstructions returns empty, the tag is omitted'} +
  • +
+
+
+ ) +} diff --git a/packages/website/src/docs/features/knowledge-injection/page.tsx b/packages/website/src/docs/features/knowledge-injection/page.tsx deleted file mode 100644 index 43795c3..0000000 --- a/packages/website/src/docs/features/knowledge-injection/page.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import BetaNotice from '@/components/BetaNotice' -import CodeEditor from '@/components/CodeEditor' - -export default function KnowledgeInjection() { - return ( -
-

知识库注入

- - - -

- 通过多层次的知识注入,让 AI 深度理解你的业务场景和应用逻辑,实现更精准的自动化操作。 -

- - {/* Custom Instruction */} -
-

Instruction - 系统指令

- -
-

- 🎯 系统级指令 -

-

- 为 AI 设定全局行为准则和工作风格。 -

-
    -
  • 定义 AI 的工作风格和交互方式
  • -
  • 设置安全边界和操作限制
  • -
  • 指定错误处理和异常情况的应对策略
  • -
  • 配置输出格式和反馈机制
  • -
-
- - -
- - {/* App Knowledge */} -
-

App Knowledge - 应用知识

- -
-

- � 业务领域知识 -

-

- 注入应用的核心业务知识,包括产品介绍、操作流程、术语定义等,让 AI 理解业务上下文。 -

-
-
-

产品知识

-
    -
  • 产品功能和特性介绍
  • -
  • 用户角色和权限体系
  • -
  • 业务规则和约束条件
  • -
-
-
-

操作指南

-
    -
  • 标准操作流程定义
  • -
  • 异常情况处理方案
  • -
  • 术语和概念解释
  • -
-
-
-
- - -
- - {/* Page Knowledge */} -
-

Page Knowledge - 页面知识

- -
-

- 📄 页面级精准指导 -

-

- 为特定页面提供精确的操作指导和元素说明,让 AI 准确理解页面结构和交互逻辑。 -

-
-
-

元素标注

-

为页面元素添加语义化描述

-
-
-

交互说明

-

- 定义元素的交互行为和预期结果 -

-
-
-

页面逻辑

-

- 说明页面的业务逻辑和状态变化 -

-
-
-
- - -
-
- ) -} diff --git a/packages/website/src/i18n/locales/en-US/common.ts b/packages/website/src/i18n/locales/en-US/common.ts index a483f00..89d8b49 100644 --- a/packages/website/src/i18n/locales/en-US/common.ts +++ b/packages/website/src/i18n/locales/en-US/common.ts @@ -29,7 +29,7 @@ export default { limitations: 'Limitations', model_integration: 'Model Integration', custom_tools: 'Custom Tools', - knowledge_injection: 'Knowledge Injection', + knowledge_injection: 'Instructions', security_permissions: 'Security & Permissions', data_masking: 'Data Masking', cdn_setup: 'CDN Setup', diff --git a/packages/website/src/i18n/locales/zh-CN/common.ts b/packages/website/src/i18n/locales/zh-CN/common.ts index 35ae7af..7c86540 100644 --- a/packages/website/src/i18n/locales/zh-CN/common.ts +++ b/packages/website/src/i18n/locales/zh-CN/common.ts @@ -28,7 +28,7 @@ export default { limitations: '使用限制', model_integration: '模型接入', custom_tools: '自定义工具', - knowledge_injection: '知识库注入', + knowledge_injection: '知识注入', security_permissions: '安全与权限', data_masking: '数据脱敏', cdn_setup: 'CDN 引入', diff --git a/packages/website/src/router.tsx b/packages/website/src/router.tsx index 9576ef4..9bd3bb8 100644 --- a/packages/website/src/router.tsx +++ b/packages/website/src/router.tsx @@ -5,7 +5,7 @@ import Header from './components/Header' // Features pages import CustomTools from './docs/features/custom-tools/page' import DataMasking from './docs/features/data-masking/page' -import KnowledgeInjection from './docs/features/knowledge-injection/page' +import Instructions from './docs/features/instructions/page' import ModelIntegration from './docs/features/model-integration/page' import SecurityPermissions from './docs/features/security-permissions/page' import BestPractices from './docs/integration/best-practices/page' @@ -80,11 +80,11 @@ export default function Router() { - +
- +
From d70f652285ab888314f4372751b8b6da914be22d Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:08:50 +0800 Subject: [PATCH 3/6] chore(website): add instructions for PageAgent demo page --- packages/website/src/page.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/website/src/page.tsx b/packages/website/src/page.tsx index d48f4f1..7605507 100644 --- a/packages/website/src/page.tsx +++ b/packages/website/src/page.tsx @@ -64,6 +64,15 @@ export default function HomePage() { interactiveBlacklist: [document.getElementById('root')!], language: i18n.language as any, + instructions: { + system: 'You are a helpful assistant on PageAgent website.', + getPageInstructions: (url) => { + const hint = url.includes('page-agent') ? 'This is PageAgent demo page.' : undefined + console.log('[instructions] getPageInstructions:', url, '->', hint) + return hint + }, + }, + // experimentalScriptExecutionTool: true, // testing server From 6b0b1218acf80de55c07243b4e16076d5fee2f24 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:18:03 +0800 Subject: [PATCH 4/6] chore: cleanup --- packages/website/src/docs/features/instructions/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/src/docs/features/instructions/page.tsx b/packages/website/src/docs/features/instructions/page.tsx index 6689672..5d6c3dc 100644 --- a/packages/website/src/docs/features/instructions/page.tsx +++ b/packages/website/src/docs/features/instructions/page.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import CodeEditor from '@/components/CodeEditor' -export default function KnowledgeInjection() { +export default function Instructions() { const { i18n } = useTranslation() const isZh = i18n.language === 'zh-CN' From 0c0c76fdd8ee8bd1790ea713a4d78eb290913595 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:19:20 +0800 Subject: [PATCH 5/6] feat: wrap user callback in try catch Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/page-agent/src/PageAgent.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/page-agent/src/PageAgent.ts b/packages/page-agent/src/PageAgent.ts index 1390b29..4059df7 100644 --- a/packages/page-agent/src/PageAgent.ts +++ b/packages/page-agent/src/PageAgent.ts @@ -370,8 +370,18 @@ export class PageAgent extends EventTarget { const systemInstructions = instructions.system?.trim() const url = await this.pageController.getCurrentUrl() - const pageInstructions = instructions.getPageInstructions?.(url)?.trim() + let pageInstructions: string | undefined + if (instructions.getPageInstructions) { + try { + pageInstructions = instructions.getPageInstructions(url)?.trim() + } catch (error) { + console.error( + chalk.red('[PageAgent] Failed to execute getPageInstructions callback:'), + error + ) + } + } if (!systemInstructions && !pageInstructions) return '' let result = '\n' From 1666c08e588b1ebcf250744e3552293cb8f188c7 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Sat, 10 Jan 2026 19:25:56 +0800 Subject: [PATCH 6/6] refactor: rename `instructions` to `custom-instructions` --- packages/website/src/components/DocsLayout.tsx | 2 +- .../features/{instructions => custom-instructions}/page.tsx | 0 packages/website/src/router.tsx | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename packages/website/src/docs/features/{instructions => custom-instructions}/page.tsx (100%) diff --git a/packages/website/src/components/DocsLayout.tsx b/packages/website/src/components/DocsLayout.tsx index 11064f7..075492d 100644 --- a/packages/website/src/components/DocsLayout.tsx +++ b/packages/website/src/components/DocsLayout.tsx @@ -34,7 +34,7 @@ export default function DocsLayout({ children }: DocsLayoutProps) { items: [ { title: t('nav.model_integration'), path: '/docs/features/model-integration' }, { title: t('nav.custom_tools'), path: '/docs/features/custom-tools' }, - { title: t('nav.knowledge_injection'), path: '/docs/features/instructions' }, + { title: t('nav.knowledge_injection'), path: '/docs/features/custom-instructions' }, { title: t('nav.security_permissions'), path: '/docs/features/security-permissions' }, { title: t('nav.data_masking'), path: '/docs/features/data-masking' }, ], diff --git a/packages/website/src/docs/features/instructions/page.tsx b/packages/website/src/docs/features/custom-instructions/page.tsx similarity index 100% rename from packages/website/src/docs/features/instructions/page.tsx rename to packages/website/src/docs/features/custom-instructions/page.tsx diff --git a/packages/website/src/router.tsx b/packages/website/src/router.tsx index 9bd3bb8..04f6193 100644 --- a/packages/website/src/router.tsx +++ b/packages/website/src/router.tsx @@ -2,10 +2,10 @@ import { Route, Switch } from 'wouter' import DocsLayout from './components/DocsLayout' import Header from './components/Header' +import Instructions from './docs/features/custom-instructions/page' // Features pages import CustomTools from './docs/features/custom-tools/page' import DataMasking from './docs/features/data-masking/page' -import Instructions from './docs/features/instructions/page' import ModelIntegration from './docs/features/model-integration/page' import SecurityPermissions from './docs/features/security-permissions/page' import BestPractices from './docs/integration/best-practices/page' @@ -80,7 +80,7 @@ export default function Router() {
- +