AI 能力
使用 BYOA daemon、AI Chat 和 Skill 系统构建工作区 AI 工作流
HackerStart 的 AI 集成以工作区为边界,通过租户功能开关控制可用能力。当前实现的核心路径是 BYOA(Bring Your Own Agent):应用不托管平台级 LLM Key,而是把请求转发到用户本机运行的 hsd daemon,再由 daemon 调用本机已安装的 AI CLI。
架构
浏览器工作区页面
→ TanStack Start API Route
→ /api/ai/chat 或 /api/ai/agent
→ 本地 hsd daemon
→ 已安装的 AI CLI
→ AG-UI SSE 流式响应- Workspace AI Shell:工作区布局会挂载 AI 侧边栏入口。当前侧边栏仍是占位体验,正式对话入口在
/ai/chat。 - AI Chat:
/ai/chat使用@tanstack/ai-react的useChat,通过/api/ai/chat接收 daemon 返回的 SSE 流。 - Agent Runtime:
/api/ai/agent-runtimes用于发现、注册、列出和移除 daemon runtime。 - Skill 系统:
/ai/skills读取 YAML Skill 定义,通过提问式流程收集活动信息。
当前 Chat 路径使用 BYOA daemon,不读取 ai.provider、ai.apiKey 或 ai.providerConfig。这些配置项已经在运行时配置系统中预留,但还没有接入当前的 Chat 执行路径。
功能开关
AI 能力由 tenant_feature_gates 表中的工作区级功能开关控制。定义位于 src/config/tenant-features.ts。
| Feature key | 说明 |
|---|---|
ai_companion | AI 能力的基础开关。其他 AI 能力会在此基础上继续检查自己的子开关。 |
ai_chat | 允许访问流式 AI Chat。 |
ai_agent | 允许连接和调用外部 Agent runtime。 |
ai_content_gen | 允许运行内容生成相关的 Skill 流程。 |
工作区 owner 或 admin 可以在 /workspace/settings 的 Feature gates 区域切换可管理的功能。/ai/settings 用于查看当前工作区的 AI 功能状态、已连接 Agent 和可用 Skill。
本地 daemon
AI daemon 位于 packages/daemon,CLI 名称是 hsd。它负责扫描本机 AI CLI、启动本地 HTTP 服务,并把 app 的请求转成 CLI 调用。
cd packages/daemon
pnpm install
pnpm build
# 扫描本机可用 AI CLI
pnpm dev setup
# 启动 daemon,默认监听 http://127.0.0.1:8765
pnpm dev start
# 查看 daemon 健康状态和 agent 列表
pnpm dev status打包后也可以通过 hsd 命令运行:
hsd setup
hsd start
hsd statusdaemon 会尝试发现这些 CLI:
| Agent id | CLI |
|---|---|
claude | Claude Code |
codex | Codex |
gemini | Gemini CLI |
opencode | OpenCode |
hermes | Hermes |
kimi | Kimi |
kiro-cli | Kiro CLI |
copilot | GitHub Copilot |
daemon 只监听 127.0.0.1,应用端也只接受 http://localhost、http://127.0.0.1 或 IPv6 localhost 的 daemon URL,避免把代理能力开放到任意远端地址。
daemon 注册
开发时,即使没有显式注册 runtime,应用也会尝试使用默认 daemon URL:
DEFAULT_DAEMON_URL=http://localhost:8765如果需要让 daemon 主动注册到应用,设置:
HSD_APP_URL=http://localhost:3000
HSD_APP_AUTH_HEADER="Cookie: <已登录浏览器会话的 cookie>"
HSD_DAEMON_ID=local然后运行:
hsd register注册请求会调用 /api/ai/agent-runtimes。该接口的 POST 和 DELETE 需要当前用户具备 Organization owner 或 admin 权限。runtime 注册会写入 InsForge PostgreSQL 的 agent_runtimes 表,按 workspace 隔离,默认 24 小时 TTL;应用重启后仍可读取未过期注册。默认 daemon 的 /health 结果只做 5 秒进程内缓存。
daemon 鉴权和运行参数
如果希望 app 调用 daemon 时带 Bearer Token,在 app 和 daemon 两侧设置同一个 HSD_TOKEN:
HSD_TOKEN=your-local-daemon-tokendaemon 端设置后,除 /health 外的请求都需要 Authorization: Bearer <token>。应用端会读取同名环境变量,并在代理到 daemon 时带上该 header。
可选参数:
| 变量 | 作用 |
|---|---|
DEFAULT_DAEMON_URL | 应用侧默认 daemon 地址。必须是本机 HTTP URL。默认值是 http://localhost:8765。 |
DEFAULT_DAEMON_AGENT_ID | 应用侧默认优先选择的 agent id。 |
HSD_TOKEN | app 与 daemon 之间的本地 Bearer Token。 |
HSD_MAX_CONCURRENT_RUNS | daemon 最大并发运行数。默认是 4。 |
HSD_APP_URL | daemon 主动注册时访问的 HackerStart 应用地址。 |
HSD_APP_AUTH_HEADER | daemon 主动注册时使用的认证 header。 |
HSD_DAEMON_ID | daemon 主动注册时使用的 daemon id,默认是 local。 |
API 路由
| 路由 | 用途 | 权限 |
|---|---|---|
POST /api/ai/chat | 工作区 Chat 入口,代理到 daemon /agent 并返回 SSE。 | 登录用户,启用 ai_companion、ai_chat、ai_agent。 |
POST /api/ai/agent | 通用 Agent 代理接口。 | 登录用户,启用 ai_companion、ai_agent,并且是 Organization owner/admin。 |
GET /api/ai/agent-runtimes | 列出当前工作区可用 runtime,并合并默认 daemon 的健康检查结果。 | 登录用户,启用 ai_companion、ai_agent。 |
POST /api/ai/agent-runtimes | 注册 daemon runtime。 | Organization owner/admin。 |
DELETE /api/ai/agent-runtimes | 移除 daemon runtime。 | Organization owner/admin。 |
/api/ai/chat 会把前端消息标准化为文本消息,并追加系统提示词:
你是 HackerStart AI 助手,帮助社区组织者管理活动、内容和成员。请用中文回答。随后它会把 threadId、runId、preferredAgent 和消息列表转发给 daemon 的 /agent 接口。
Skill 系统
Skill 是面向业务流程的 YAML 定义。当前实现是确定性的提问式引擎,不会自动调用 LLM 生成最终文案。
相关代码:
src/ai/skills/schema.ts
src/ai/skills/skill-loader.server.ts
src/ai/skills/skill-runner.ts
src/ai/skill-agent-server.ts
src/ai/skill-agent-runtime.server.ts
src/db/queries/skill-runs.ts当前内置 Skill:
| Skill | 说明 |
|---|---|
lecture-online | 线上讲座活动信息收集。 |
content-event-promo | 活动推广文案信息收集。 |
content-event-summary | 活动回顾信息收集。 |
Skill 定义位于:
src/ai/skills/definitions/每个 YAML 文件包含:
name、label、description、iconquestions:提问列表,支持text、number、boolean、select、locationthenAsk/ifValue:条件追问skipIf:简单条件跳过outputs:声明预期输出类型validation:必填字段和最少问答轮数
Skill 运行状态保存在 InsForge PostgreSQL 的 skill_runs 表中,有 30 分钟空闲 TTL,并按 tenantId + userId 校验归属。服务端重启后,未过期的 run state 仍可继续;当前前端只把 runId 放在组件状态里,刷新页面后不会自动恢复旧流程。
本地验证
建议按下面顺序验证:
# 1. 应用侧类型和测试
pnpm typecheck
pnpm test
# 2. daemon 包
cd packages/daemon
pnpm typecheck
pnpm build
pnpm dev setup
pnpm dev start启动应用后:
- 登录一个属于目标工作区的用户。
- 在
/workspace/settings启用ai_companion、ai_chat、ai_agent。如需 Skill,启用ai_content_gen。 - 打开
/ai/settings,确认 Agent 连接和功能状态。 - 打开
/ai/chat,发送消息,确认能收到流式响应。 - 打开
/ai/skills,完成一次 Skill 问答流程。
常见问题
Chat 返回 “Agent daemon is not connected”
确认 daemon 已启动,并且应用侧的 DEFAULT_DAEMON_URL 指向本机 HTTP 地址。默认是:
DEFAULT_DAEMON_URL=http://localhost:8765也可以访问 daemon 健康检查:
curl http://127.0.0.1:8765/health注册 runtime 返回 403
POST /api/ai/agent-runtimes 需要 Organization owner 或 admin 权限。普通工作区成员可以查看 runtime,但不能注册或移除 runtime。
Skill 页面无法启动流程
确认当前工作区启用了 ai_companion 和 ai_content_gen。Skill 列表只需要 ai_companion,但开始或回答 Skill 问题需要内容生成能力。
已配置 ai.apiKey 但 Chat 没有使用
这是当前实现的预期行为。Chat 走 BYOA daemon 路径,不读取运行时配置中的 AI provider key。