1. 项目概述:一个用Elixir构建的、可深度定制的个人AI智能体
如果你对AI智能体(Agent)感兴趣,并且希望有一个完全由自己掌控、能深度融入你的工作流、甚至能记住你的习惯和偏好的“数字伙伴”,那么Goodwizard值得你花时间研究。它不是一个简单的聊天机器人包装,而是一个基于Elixir语言和Jido框架构建的、功能完整的个人AI操作系统。它的核心魅力在于“可塑性”——从底层记忆结构到外在性格,你都可以通过编辑几个Markdown文件来定义。想象一下,你不仅是在“使用”一个AI,更是在“塑造”一个专属于你的、不断学习和成长的数字实体。
这个项目由agoodway团队开源,其设计哲学非常清晰:将AI的能力从封闭的聊天窗口解放出来,变成一个可以通过文件、命令行、定时任务、甚至心跳文件来触发的后台服务。这意味着你可以通过写一个脚本、修改一个文件,或者设置一个定时任务,来让AI帮你处理邮件摘要、检查项目进度、自动整理知识库,而无需每次都打开一个聊天界面。它把AI变成了一个像Cron或Systemd一样的基础设施组件。
2. 核心架构与设计哲学解析
2.1 为什么选择Elixir和Jido?
Goodwizard的技术栈选择非常有意思。Elixir是一门构建在Erlang虚拟机(BEAM)上的函数式语言,以其高并发、容错性和“任其崩溃”的哲学闻名。Jido则是一个专门为构建AI智能体而设计的Elixir框架。这两者的结合,为Goodwizard带来了几个先天优势:
- 高并发与隔离性:Elixir的轻量级进程(Process)是构建并发系统的绝佳模型。Goodwizard利用这一点,可以轻松地同时运行数十个独立的“子智能体”(Sub-agent),每个都处理不同的任务(如定时任务、心跳触发),彼此之间完全隔离。一个任务崩溃不会影响主会话或其他任务,这比用Python或Node.js写的单线程Agent要稳健得多。
- 热代码升级与状态管理:BEAM虚拟机支持热更新,理论上Goodwizard可以在不停止服务的情况下更新其技能或逻辑。虽然当前版本未直接暴露此功能,但底层框架为未来的动态扩展提供了可能。
- “工具调用”作为一等公民:Jido框架原生将工具调用(Tool Calling)和ReAct(推理-行动)循环作为核心抽象。这使得Goodwizard能非常自然地让AI决定何时、如何使用文件系统、浏览器、Shell等工具,而不是写死一堆if-else逻辑。
注意:选择Elixir也意味着一定的学习门槛。如果你不熟悉函数式编程或OTP(Elixir的并发框架),初期配置和调试可能会有些挑战。但一旦上手,其架构的清晰度和可靠性会带来巨大回报。
2.2 模块化的工作空间:智能体的“数字大脑”
Goodwizard没有将智能体的“人格”和“知识”硬编码在代码里,而是将其外化到一个文件系统工作空间(默认是priv/workspace/)。这是它最精妙的设计之一。你可以把这个工作空间想象成智能体的“大脑皮层”,由几个关键文件构成:
IDENTITY.md:定义智能体“是谁”。包括名字、角色(如“高效的个人助理”、“创意伙伴”)、沟通语气(正式、随意、鼓励式)。这是塑造第一印象的关键。SOUL.md:定义智能体的“价值观和行为准则”。比如“始终优先考虑用户的隐私”、“在提供建议时解释推理过程”、“承认知识边界”。这相当于它的道德罗盘和操作原则。USER.md:智能体所了解的“关于你的一切”。你的职业、常用工具、项目目标、个人偏好(比如“我讨厌冗长的邮件”、“我喜欢用Markdown做笔记”)。这是它提供个性化服务的基础。MEMORY.md:动态更新的语义记忆。这不是聊天记录,而是智能体从中提炼出的关于你的持久性认知,比如“用户通常在周二下午进行代码评审”、“用户对Python的异步编程比较熟悉”。这个文件会随着对话被智能体主动更新。
启动时,一个叫Preamble.Hydrator的模块会将这些文件,连同当前可用的工具列表、知识库模式等运行时状态,组合成一个完整的“系统提示词”(System Prompt)。这意味着,你只需编辑这些Markdown文件,就能从根本上改变智能体的行为和知识背景,无需改动一行代码。
2.3 三层记忆系统:从短期对话到长期学习
一个只会聊天的AI是“金鱼”,而Goodwizard试图构建的是“大象”般的记忆。它的记忆系统分为三层,模拟了人类不同的记忆类型:
- 语义记忆(Semantic):如上文所述,存储在
MEMORY.md中。是智能体对你形成的抽象化、概括性的认知。 - 情景记忆(Episodic):存储在
memory/episodic/目录下,每个文件都是一次不可变的“经历”记录。例如:“2024-05-10:成功帮用户使用grep命令在项目日志中找到了错误。”、“2024-05-11:用户拒绝了关于使用新笔记工具的建议。”。这些是事实性的历史档案,供智能体在需要参考过去具体事件时检索。 - 程序性记忆(Procedural):存储在
memory/procedural/目录下,是智能体“学会”的工作流程或模式。例如:“如何为用户生成日报”可能是一个程序性记忆。它会记录该流程被成功执行的次数、最后一次使用时间,并有一个“置信度”分数。不常用的流程会随时间“衰减”,最终可能被归档。这是实现智能体自主学习和技能优化的关键机制。
当一次对话会话变得很长时,Goodwizard会启动一个“记忆巩固”过程,自动从对话记录中提取新的情景记忆和程序性记忆,并更新语义记忆。这模拟了人类睡眠中记忆巩固的过程,使得智能体能够真正从交互中学习。
3. 核心功能与实操指南
3.1 知识库:结构化的个人数据枢纽
Goodwizard内置了一个基于文件的知识库,支持“人物”、“地点”、“事件”、“笔记”、“任务”、“公司”等实体类型。它的运作方式很优雅:
- 模式驱动:每种实体类型都有一个JSON Schema定义(在代码中)。这确保了数据的结构化和有效性。
- 文件存储:每个实体都保存为一个Markdown文件,包含YAML前端元数据(存储结构化字段)和正文内容。例如,一个“人物”实体文件可能包含
name、role、contact等字段。 - 自动生成工具:启动时,系统会根据这些Schema,为每种实体类型自动生成对应的工具函数,如
create_person、search_notes、update_task。这意味着你可以直接对智能体说:“把‘张三’加到知识库里,他是某公司的后端工程师,邮箱是zhangsan@example.com”,智能体就会调用相应的工具来创建这个实体。 - 实体关联:实体之间可以通过
“type/uuid”格式的字符串相互引用。例如,一个“任务”实体可以关联到多个“人物”实体(负责人)。
实操心得:初期建议从“笔记”和“任务”类型开始用起。你可以让智能体帮你记录会议纪要(创建一个“笔记”实体),或者管理待办清单(创建“任务”实体)。知识库的力量在于关联查询,例如你可以问:“上个月所有和‘项目A’相关的会议笔记有哪些?”
3.2 技能系统:可插拔的能力扩展
技能(Skills)是Goodwizard扩展AI能力的主要方式。它采用了一种聪明的“两层加载”设计:
- 技能摘要:每个技能目录(如
skills/weather/)下都有一个SKILL.md文件。系统启动时,会提取所有技能的摘要部分,并将其嵌入到每次对话的系统提示词中。这样智能体就知道有哪些技能可用,以及它们的简要用途。 - 按需加载:只有当智能体决定要使用某个技能时(比如用户问“今天天气怎么样”),它才会通过
activate_skill工具去加载该技能SKILL.md文件的完整内容(通常包含详细的API调用指令、参数说明、示例等)。
这种设计完美平衡了上下文长度限制和功能丰富性。项目自带了一个weather技能,它整合了wttr.in和Open-Meteo两个天气数据源。你可以参考它来创建自己的技能,比如send_email、query_database或control_smart_home。
创建自定义技能步骤:
- 在
priv/workspace/skills/下新建一个目录,例如my_skill。 - 在该目录下创建
SKILL.md文件。 - 文件结构通常包括:
# Summary:一两句话描述技能用途(这部分会被摘要)。# Full Instructions:详细的调用说明、所需参数、API端点、示例请求/响应。# Examples:用户可能如何触发此技能的对话示例。
- 重启Goodwizard,你的新技能摘要就会被自动识别。
3.3 心跳与调度:让智能体自主运行
这是Goodwizard从“交互工具”蜕变为“自主系统”的核心功能。
心跳(Heartbeat): 这是一个由GenServer(Elixir的通用服务器)实现的定时轮询机制。它每隔N分钟(可配置)检查一次HEARTBEAT.md文件的修改时间。如果发现文件被改动,它就会读取文件内容,将其作为提示词发送给智能体处理,并将回复保存起来。
这打开了无限的自动化可能性。你可以用任何能写文件的方式触发AI:
- 一个
cron作业:echo “生成昨日销售报告摘要” > HEARTBEAT.md - 一个Git钩子:在代码推送后,让CI/CD流水线写入“分析本次提交的变更”。
- 一个监控脚本:当服务器磁盘使用率超过90%时,写入“警告!磁盘空间不足,请分析并给出清理建议”。
调度(Scheduling): Goodwizard支持标准的cron表达式来定义周期性任务,也支持@daily、@hourly这样的别名。每个定时任务触发时,都会在一个完全隔离的子智能体中运行,确保不会干扰你当前可能正在进行的交互会话。
配置一个每日早安简报的示例: 在config.toml的[scheduled_tasks]部分(或通过对话添加):
[[scheduled_tasks]] schedule = "0 9 * * *" # 每天上午9点 prompt = "现在是早上9点。请检查我的知识库中所有状态为‘进行中’的任务,总结今日待办事项,并查看天气。以简洁的列表格式回复。" channel = "cli" # 或 “telegram” chat_id = "morning_brief"3.4 工具集:智能体的“手脚”
Goodwizard为智能体装备了一套强大的工具,使其能与现实世界交互:
| 工具类别 | 能力说明 | 安全考量 |
|---|---|---|
| 文件系统 | 在工作空间内读写、编辑、搜索文件。 | 默认限制在工作空间内,防止误操作系统文件。 |
| Shell执行 | 运行命令行指令。 | 通过deny_patterns配置正则表达式黑名单,可屏蔽rm -rf /、dd等危险命令。超时机制防止死循环。 |
| 浏览器自动化 | 使用Vibium或Playwright驱动浏览器进行点击、输入、截图、抓取内容。 | 可在无头模式运行,适合服务器环境。 |
| 知识库 | 对内置实体类型的增删改查。 | 由JSON Schema校验,保证数据一致性。 |
| 记忆 | 对三层记忆系统的读写操作。 | 智能体可以自主决定记住或回忆什么。 |
| 消息 | 向指定的“房间”(如CLI会话、Telegram聊天)发送消息。 | 用于任务完成通知或主动汇报。 |
| 子智能体 | 派生出独立的智能体来处理特定子任务。 | 受max_concurrent_agents限制,避免资源耗尽。 |
| 调度 | 创建和管理定时或一次性任务。 | 任务持久化到磁盘,重启后不丢失。 |
关于Shell工具的安全实践: 在生产环境或处理敏感操作时,务必仔细审查和配置config.toml中的[tools.exec]部分的deny_patterns。默认列表已经包含了一些危险模式,但你应根据自己的需要增补。例如,如果你完全不想让智能体接触数据库,可以加入.*(drop|alter)\\s+table.*之类的规则。
4. 从零开始部署与深度配置
4.1 环境准备与初始化
假设你已经在系统上安装了Elixir 1.17+和Just命令运行器。
# 1. 克隆项目 git clone https://github.com/agoodway/goodwizard.git cd goodwizard # 2. 获取依赖 mix deps.get # 3. 运行初始化设置 mix goodwizard.setupmix goodwizard.setup这个命令是关键,它会创建整个工作空间目录结构、默认的配置文件config.toml,以及那些核心的身份文件(IDENTITY.md,SOUL.md等)的模板。你的“塑造智能体”之旅就从编辑这些文件开始。
4.2 核心身份文件定制指南
不要跳过这一步,这是赋予Goodwizard灵魂的过程。
编辑
IDENTITY.md:- Name & Role:给它起个名字,定义核心角色。例如:“CodeWizard,你的专属软件开发助手”。
- Tone & Style:定义沟通风格。是像导师一样严谨,还是像朋友一样随意?例如:“使用专业但友好的语气。在解释复杂概念时使用比喻。避免使用‘呃’、‘嘛’等不确定的词语。”
- Capabilities:简要说明它能做什么(工具概览),让它在自我介绍时更准确。
编辑
SOUL.md:- 核心原则:列出最高行为准则。例如:“1. 用户隐私和安全至高无上。2. 在采取任何具有潜在影响的行动(如运行命令、修改文件)前,必须明确征得用户同意。3. 如果对某件事不确定,应坦诚说明,而非猜测。”
- 推理框架:指导它如何思考。例如:“遵循ReAct模式:先思考(Reason),再行动(Act)。在思考步骤中,简要分析目标、可用工具和潜在风险。”
编辑
USER.md:- 关于我:你的职业、技术栈、常用工具(编辑器、编程语言、项目管理软件)。
- 工作流偏好:你喜欢的交互方式。例如:“我喜欢你提供选项让我选择,而不是直接执行。报告请尽量用Markdown列表或表格。对于代码,优先提供片段而非完整文件。”
- 当前项目:你正在进行的重点工作,方便它提供上下文相关的帮助。
4.3 通道配置:CLI与Telegram
CLI通道:默认启用。运行mix goodwizard.cli会进入一个交互式REPL。这是开发和调试的主要界面。会话历史会保存在sessions/目录下,方便回溯。
Telegram通道配置详解:
- 按项目文档创建Bot并获取Token,填入
.env文件。 - 在
config.toml中启用:[channels.telegram] enabled = true allow_from = [123456789] # 你的Telegram User ID,从@userinfobot获取 - 高级功能:角色覆盖。你可以让Telegram上的Bot和CLI里的智能体表现出略微不同的性格。这在
config.toml中通过character_overrides实现:
这个[channels.telegram.character_overrides] preamble = "你现在在Telegram上与我对话。请使你的回复更加简洁、活泼,可以适当使用表情符号。在提供链接时,请使用Markdown内联链接格式。"preamble会附加到Telegram通道的系统提示词中,从而覆盖或调整基础身份设定。
4.4 模型与性能调优
config.toml中的[agent]部分控制着核心LLM的行为:
model:默认使用anthropic:claude-sonnet-4-5。你也可以尝试anthropic:claude-haiku-3(更快、更便宜)或其他支持的模型。max_tokens:控制单次回复的最大长度。对于复杂的分析任务,可以调高(如16384)。对于心跳触发的简短任务,可以调低以节省成本。temperature:创造性。0.7是一个不错的平衡点。如果你需要更确定、可重复的输出(如生成数据),可以降到0.2;如果需要更多创意,可以升到0.9。max_tool_iterations:ReAct循环的最大次数。防止智能体陷入“思考-行动”的死循环。对于简单任务,10可能就够了;对于需要多步骤探索的复杂任务,可以设为20或更高。memory_window:保留在对话上下文中的最近消息数量。这直接影响API调用的token消耗。如果你的对话很长且不想丢失早期上下文,可以调大,但需注意成本。
5. 实战场景与进阶技巧
5.1 场景一:个人知识管理与日报生成
目标:让Goodwizard自动整理你一天中产生的零散信息,并生成结构化日报。
实现步骤:
- 知识库录入:养成习惯,将任何想法、会议记录、待办事项通过对话让Goodwizard存入知识库。例如:“将‘下午与团队讨论项目B的API设计,决定采用RESTful风格’保存为一条笔记,关联到‘项目B’和‘团队会议’标签。”
- 创建日报技能:编写一个
daily_report技能。在SKILL.md中,详细指导智能体如何查询知识库:检索过去24小时内创建或修改的所有“笔记”和“任务”实体,按项目或标签分类,总结进展和待办项。 - 设置定时心跳:创建一个cron任务或使用Just命令,在每天下班时间(如下午6点)向
HEARTBEAT.md写入:“现在执行每日报告技能,总结我今天的工作进展和明天的待办事项。” - 输出:智能体执行技能,生成Markdown格式的日报,并可以通过Telegram Bot直接发送给你,或者保存到工作空间的一个指定文件中。
5.2 场景二:自动化网站监控与警报
目标:监控某个网页内容的变化(如产品价格、职位发布、博客更新),并在变化时通知你。
实现步骤:
- 创建监控技能:编写一个
monitor_website技能。利用浏览器工具访问指定URL,提取关键内容(如价格数字、文章标题列表),计算哈希值或与上次抓取的内容进行差异对比。 - 利用程序性记忆:让技能将每次抓取的结果(或哈希)作为一个“情景记忆”保存。下次执行时,先读取上次的记忆进行对比。
- 设置高频心跳:将
heartbeat.interval_minutes设置为15或30分钟。 - 触发逻辑:写一个简单的Shell脚本,定期(比如每小时)运行。脚本首先调用
monitor_website技能(通过写入HEARTBEAT.md),如果技能检测到变化,就在脚本中通过curl命令调用Telegram Bot API(或其他通知服务)直接向你发送警报。Goodwizard负责复杂的抓取和对比逻辑,外部脚本负责轻量的调度和通知。
5.3 场景三:作为开发助手进行代码库交互
目标:在CLI中,让Goodwizard帮你理解代码、查找bug、甚至生成小段代码。
配置要点:
- 扩大文件系统权限:在
config.toml中,将[tools]部分的restrict_to_workspace设置为false(请务必谨慎,并配合严格的Shell命令黑名单)。或者,更安全的方式是将你的代码库符号链接(symlink)到工作空间内。 - 增强
USER.md:在USER.md中详细说明你的项目技术栈、目录结构、代码规范。 - 使用方式:
- 代码解释:“请分析
lib/goodwizard/preamble.ex文件中的hydrate/1函数,解释它的主要逻辑。” - Bug查找:“我在运行
mix test test/goodwizard_test.exs:25时遇到一个错误,错误信息是…。请结合相关代码帮我分析可能的原因。” - 代码生成:“在
lib/my_app/目录下,按照现有模式,创建一个新的上下文模块Blog,包含Posts和Comments两个模式。”
- 代码解释:“请分析
重要心得:让AI直接操作生产代码库存在风险。最佳实践是:① 始终在独立的开发分支或副本上进行。② 要求智能体在修改任何文件前,必须提供完整的差异预览(diff),并等待你的明确确认。③ 将这条规则写入
SOUL.md的核心原则中。
6. 故障排除与性能优化
6.1 常见问题速查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
启动时mix deps.get失败 | 网络问题或Hex镜像不可用 | 运行mix hex.repo add hex https://mirrors.cloud.tencent.com/hex切换国内镜像,或检查代理设置。 |
mix goodwizard.setup不创建文件 | 依赖未正确安装或路径权限问题 | 确保mix deps.get成功。检查当前用户对项目目录有写权限。 |
| CLI启动后无响应或立即退出 | Elixir版本不匹配或环境变量缺失 | 确认Elixir版本≥1.17。检查.env文件是否存在且包含有效的ANTHROPIC_API_KEY。运行echo $ANTHROPIC_API_KEY验证环境变量已加载。 |
| 智能体不调用工具,只是空想 | 系统提示词可能被覆盖或工具注册失败 | 检查priv/workspace/下的身份文件是否格式正确。查看启动日志,确认所有工具(特别是知识库工具)已成功加载。尝试在SOUL.md中强调“积极使用工具解决问题”。 |
| Telegram Bot不回复消息 | Token错误、配置未启用或网络问题 | 1. 确认.env中的TELEGRAM_BOT_TOKEN正确。2. 确认config.toml中[channels.telegram]的enabled = true。3. 检查服务器网络是否能访问Telegram API。4. 查看应用日志_build/dev/log/erlang.log.*。 |
| 心跳文件被读取后内容未清空 | 这是设计如此 | 心跳机制基于文件修改时间。只有内容变化才会触发。如果想再次触发,需要修改文件内容(如追加一个空格再保存)。 |
| 执行Shell命令被拒绝 | 命令匹配了deny_patterns黑名单 | 检查config.toml中[tools.exec]的deny_patterns。对于需要运行的安全命令,可以临时调整黑名单规则,或考虑将其封装成一个安全的自定义脚本供智能体调用。 |
| 浏览器工具无法启动 | 缺少Chromium或Playwright依赖 | 如果使用playwright适配器,需运行mix playwright.install。确保系统已安装必要的库(如libnss3,libxss1等)。在Docker中运行时,需要使用包含浏览器依赖的镜像。 |
6.2 性能与资源管理
- 控制并发量:
scheduled_tasks.max_concurrent_agents(默认50)限制了同时运行的子智能体数量。如果你的定时任务密集或处理很慢,可能会排队。监控日志,如果发现任务被跳过,可以考虑适当增加此值,但需权衡服务器资源。 - 管理会话内存:
agent.memory_window控制保留的对话轮数。过大的值会导致每次API调用携带大量历史,增加成本和延迟。对于长期运行的Telegram会话,可以设置一个合理的值(如30-50),并依赖“记忆巩固”机制将重要信息转移到长期记忆中。 - 浏览器工具超时:
browser.timeout(默认30秒)控制单个浏览器操作的等待时间。对于加载缓慢的页面,可能需要调高。tools.exec.timeout(默认60秒)控制Shell命令超时。 - 日志与监控:Goodwizard使用标准的Elixir Logger。可以通过修改
config/runtime.exs来调整日志级别(如设置为:info减少调试噪音)。关注_build/dev/log/下的日志文件,是排查问题的第一手资料。
6.3 自定义与扩展思路
当你熟悉基础功能后,可以从以下方向深度定制:
- 开发新工具:Jido框架使得添加新工具相对简单。你可以参照
lib/goodwizard/tools/下的现有模块,创建一个新的工具模块,实现Goodwizard.Tools行为(Behaviour),并将其注册到工具列表中。例如,添加一个连接内部数据库查询的工具,或调用一个内部API。 - 集成外部系统:利用“心跳”和“Shell工具”,Goodwizard可以成为各种系统的胶水层。例如,让CI/CD流水线在部署失败时写入心跳文件,Goodwizard分析日志并给出修复建议;或者让智能体定期查询健康检查端点,并在异常时通知你。
- 优化记忆策略:默认的记忆巩固逻辑可能不适合所有场景。你可以深入研究
lib/goodwizard/memory/consolidation.ex模块,调整从对话中提取情景和程序性记忆的规则,使其更符合你的需求。 - 前端界面:虽然提供了CLI和Telegram,但你完全可以基于其API(通过心跳文件或直接调用内部模块)构建一个Web前端,提供更丰富的交互体验。
Goodwizard不是一个开箱即用的消费级产品,而是一个为开发者和技术爱好者准备的“智能体构建套件”。它的力量来自于其高度的模块化和可编程性。投入时间配置它、教导它、将它融入你的流程,你最终收获的将不仅仅是一个工具,而是一个能够随着你一起进化的数字化助手。