跳转到内容

自定义 Agent 与工具编排

自定义 Agent 与工具编排

学习目标

理解 Khoj 如何让用户创建自定义 Agent,包括声明式工具集选择、Persona 安全验证、模型绑定和隐私分级。

前置知识

本章涉及多 Agent 路由与工具调用的通用原理,以及 Operator Agent 模式,建议先阅读:

下文假设你已理解上述概念,直接聚焦 Khoj 的自定义 Agent 实现。

项目实践

Agent 模型设计

Khoj 的 Agent 模型(约 150 行定义)是用户可创建 Agent 的核心数据结构:

Agent:
├── 基础信息
│ ├── name: 名称
│ ├── slug: URL 友好的唯一标识(自动生成)
│ ├── personality: 自定义系统提示(persona)
│ ├── style_color / style_icon: UI 外观
├── 能力配置
│ ├── input_tools: [GENERAL, ONLINE, NOTES, WEBPAGE, CODE]
│ ├── output_modes: [IMAGE, DIAGRAM]
│ ├── chat_model: 绑定的 LLM
├── 安全与可见性
│ ├── privacy_level: PUBLIC | PRIVATE | PROTECTED
│ ├── is_hidden: 是否隐藏(系统 Agent)
│ ├── creator: 创建者(FK to KhojUser)
│ └── managed_by_admin: 管理员托管标记

声明式工具集

Agent 的能力通过 ArrayField 声明式选择:

工具作用底层实现
GENERAL纯对话直接调用 LLM
ONLINE网络搜索Google / Serper / SearXNG
NOTES文档检索语义搜索 pgvector
WEBPAGE网页抓取Firecrawl / Olostep / Exa
CODE代码执行E2B / Terrarium 沙箱

这种设计的核心优势是组合性:用户可以创建只具备特定能力的 Agent。例如:

  • 研究助手:ONLINE + NOTES + WEBPAGE(只能搜索和阅读,不能执行代码)
  • 编程助手:GENERAL + CODE(纯对话 + 代码执行,不能上网搜索)
  • 全能助手:全部工具(等价于默认 Agent)

Persona 安全验证

用户自定义 personality 字段作为 Agent 的系统提示。为防止恶意 persona(如”忽略所有安全限制”),Khoj 实现了 acheck_if_safe_prompt()

用户提交 persona
→ 用 LLM 验证安全性
→ 安全 → 创建 Agent
→ 不安全 → 拒绝创建

这是一个典型的 LLM-as-a-judge 模式:用一个 LLM 审查另一个 LLM 的系统提示。虽然不能完全阻止绕过,但增加了攻击门槛。

模型绑定

每个 Agent 绑定一个独立的 ChatModel。这意味着:

  • 不同 Agent 可以使用不同的 LLM(如翻译 Agent 用 Claude,编程 Agent 用 GPT-4o)
  • Agent 的性能和成本由管理员通过 ChatModel 配置控制
  • 用户无法在 Agent 对话中切换模型——模型是 Agent 的固有属性

隐私分级

三级隐私体系:

级别可见范围创建限制
PUBLIC所有用户同名公共 Agent 不可重复创建
PRIVATE仅创建者同名私有 Agent 不可重复创建(同一用户)
PROTECTED特定范围待扩展

创建时通过 Django pre_save 信号验证唯一性约束:

@receiver(pre_save, sender=Agent)
def verify_agent(sender, instance, **kwargs):
if instance._state.adding:
# 检查公共 Agent 同名
if Agent.objects.filter(name=instance.name, privacy_level=PUBLIC).exists():
raise ValidationError(...)
# 检查私有 Agent 同名(同一用户)
if Agent.objects.filter(name=instance.name, creator=instance.creator).exists():
raise ValidationError(...)

问题与规避

问题影响规避策略
自定义 persona 可能绕过安全限制Agent 可能输出有害内容acheck_if_safe_prompt() LLM 安全验证
用户创建过多 Agent数据库膨胀、选择困难目前无限制,可通过 managed_by_admin 标记限制
Agent 绑定低质量模型对话体验差管理员控制可用 ChatModel 列表
公共 Agent 名称冲突用户无法创建同名 Agent唯一性约束 + 清晰错误提示

设计取舍

为什么 Agent 绑定单一模型而不是运行时可切换?

绑定模型简化了 Agent 的定义——每个 Agent 有固定的”能力预算”。用户不需要在每次对话时选择模型,管理员也可以精确控制成本。缺点是灵活性降低:如果绑定模型下线或质量下降,需要管理员手动更换。

为什么使用 ArrayField 而非独立的 Agent-Tool 关联表?

PostgreSQL 的 ArrayField 在工具集固定且小型时更高效——一次查询即可获取所有工具配置,不需要 JOIN。如果未来需要记录工具级别的权限、统计使用频率等,可能需要改为关联表。

参考来源