【硬核实战】手撸一个本地AI Agent:从零构建 “OpenClaw“ (Node.js + DeepSeek)

【硬核实战】手撸一个本地AI Agent:从零构建 “OpenClaw” (Node.js + DeepSeek)

摘要:最近 AI Agent(智能体)的概念火遍全网。与其做一个单纯的“调包侠”,不如亲自动手写一个!本文将带你从零开始,使用 Node.js 构建一个运行在本地的、拥有“系统操作权限”的 AI 助手 —— 我们将其命名为 OpenClaw。它不仅能陪你聊天,还能帮你执行终端命令、读写文件。

关键词:AI Agent, Node.js, DeepSeek, OpenAI API, 本地部署, 自动化, Function Calling

1. 什么是 OpenClaw?为什么你需要一个本地 Agent?

传统的 ChatGPT 或 Claude 网页版虽然强大,但它们像被关在沙盒里的天才——它们无法直接访问你的本地文件,也无法帮你执行终端命令(比如“帮我把下载文件夹里所有的 PDF 移动到 Documents 目录”)。

OpenClaw 的核心理念是:给 AI 装上“爪子”(Tools)

在这篇教程中,我们将实现一个具备以下功能的 Agent:

  1. 大脑:接入 DeepSeek-V3 或 GPT-4(通过 OpenAI 兼容接口)。
  2. 感官:能够读取用户在终端的输入。
  3. 爪子:能够执行 Shell 命令、读取本地文件。
  4. 记忆:基于对话历史的上下文理解。

2. 环境准备 (Prerequisites)

可以添加qq交流群获取工具1078800977
在开始之前,请确保你的环境满足以下要求:

  • 操作系统:MacOS / Linux / Windows (WSL2 推荐)
  • Node.js:v18 或更高版本
  • API Key:你需要一个 OpenAI 格式的 API Key(推荐使用 DeepSeek,性价比极高;或者 OpenAI、Anthropic)。

初始化项目

打开终端,创建一个名为 openclaw 的文件夹并初始化:

mkdir openclaw cd openclaw npm init -y 

修改 package.json,添加 "type": "module" 以支持 ES6 模块(这很重要!):

{"name":"openclaw","version":"1.0.0","type":"module",...}

安装必要的依赖:

# openai: 用于连接大模型标准接口# dotenv: 用于管理环境变量,保护你的 Key# chalk: 用于终端彩色输出(提升开发体验)npminstall openai dotenv chalk 

3. 第一步:配置“大脑”与基础连接

在项目根目录下创建一个 .env 文件,填入你的 API Key。这里以 DeepSeek 为例:

# 如果使用 DeepSeek OPENAI_API_KEY=sk-your-deepseek-key-here OPENAI_BASE_URL=https://api.deepseek.com # 如果使用 OpenAI # OPENAI_API_KEY=sk-your-openai-key-here # OPENAI_BASE_URL=https://api.openai.com/v1 

4. 核心代码编写:Agent 的灵魂

我们将所有逻辑写在一个 index.js 文件中。为了方便大家理解,我们将代码分为三个部分:工具定义执行逻辑主循环

新建 index.js,将以下代码复制进去。

4.1 引入依赖与配置

import OpenAI from'openai';import dotenv from'dotenv';import chalk from'chalk';import readline from'readline';import{ exec }from'child_process';import util from'util';// 加载环境变量 dotenv.config();// 将 exec Promise 化,方便异步调用const execPromise = util.promisify(exec);// 配置 OpenAI 客户端const client =newOpenAI({apiKey: process.env.OPENAI_API_KEY,baseURL: process.env.OPENAI_BASE_URL,});// 创建终端输入接口const rl = readline.createInterface({input: process.stdin,output: process.stdout }); console.log(chalk.blue.bold("🤖 OpenClaw v1.0 (Local Agent) is online.")); console.log(chalk.gray("Type 'exit' to quit.\n"));

4.2 定义“爪子” (Tools Schema)

这是 Agent 最关键的部分。我们需要告诉 AI:“你可以使用这个工具来操作电脑。”

// 定义工具描述 (Schema)const tools =[{type:"function",function:{name:"execute_shell_command",description:"Execute a shell command on the local machine. Use this to list files, read content, check system status, or run scripts.",parameters:{type:"object",properties:{command:{type:"string",description:"The shell command to execute (e.g., 'ls -la', 'cat package.json', 'whoami')."}},required:["command"]}}}];// 实际执行工具的函数asyncfunctionexecuteShellCommand(command){ console.log(chalk.cyan(`> 🔧 OpenClaw is executing: ${command}`));try{// 安全提示:生产环境中这里应该加一个白名单或确认步骤const{ stdout, stderr }=awaitexecPromise(command);if(stderr){// 有些命令虽然成功但会输出到 stderr,这里视情况处理return`Output: ${stdout}\nStderr: ${stderr}`;}return stdout ||"Command executed successfully with no output.";}catch(error){return`Error executing command: ${error.message}`;}}

4.3 实现 ReAct 循环 (Think -> Act -> Observe)

这是 OpenClaw 的核心逻辑。它会判断大模型是否返回了 tool_calls,如果是,则执行命令并将结果“喂”回给大模型。

// 初始化对话历史,设定 System Promptconst messages =[{role:"system",content:`You are OpenClaw, a helpful AI assistant running on the user's local machine. You have permission to access the file system and run commands via the 'execute_shell_command' tool. Rules: 1. When asked to do something on the computer, USE THE TOOL. Do not guess. 2. Be concise in your responses. 3. If the output is long, summarize it unless asked for details. `}];// 处理单次对话流asyncfunctionprocessChat(userBuffer){// 1. 发送请求给 LLMconst completion =await client.chat.completions.create({messages: messages,model:"deepseek-chat",// ⚠️ 注意:根据你的服务商修改模型名称,如 "gpt-4o"tools: tools,tool_choice:"auto",});const responseMessage = completion.choices[0].message;// 2. 检查 AI 是否想调用工具if(responseMessage.tool_calls){// 把 AI 的“思考/调用请求”加入历史,保持上下文完整 messages.push(responseMessage);// 遍历所有工具调用请求(有时 AI 会一次性调用多个工具)for(const toolCall of responseMessage.tool_calls){if(toolCall.function.name ==='execute_shell_command'){const args =JSON.parse(toolCall.function.arguments);// --- 真正执行命令的地方 ---const output =awaitexecuteShellCommand(args.command);// -----------------------// 3. 将工具的执行结果(Observation)返回给 AI messages.push({tool_call_id: toolCall.id,role:"tool",name:"execute_shell_command",content: output,// 这里是命令行的真实输出});}}// 4. 让 AI 拿到工具结果后,再次生成最终回复const secondResponse =await client.chat.completions.create({messages: messages,model:"deepseek-chat",});return secondResponse.choices[0].message.content;}else{// 如果没有调用工具,直接返回文本回复 messages.push(responseMessage);return responseMessage.content;}}

4.4 启动交互循环

functionask(){ rl.question(chalk.green('You: '),async(input)=>{if(input.toLowerCase()==='exit'){ console.log(chalk.gray("Goodbye!")); rl.close();return;}// 记录用户输入 messages.push({role:"user",content: input });try{ process.stdout.write(chalk.gray("OpenClaw is thinking...\r"));const finalResponse =awaitprocessChat(input);// 清除 thinking 提示并输出回答 process.stdout.clearLine(); process.stdout.cursorTo(0); console.log(chalk.yellow('OpenClaw: ')+ finalResponse +'\n');}catch(error){ console.error(chalk.red("\nError:"), error.message);}ask();// 递归调用,保持持续对话});}// 启动!ask();

5. 实战演示 (Demo Time)

现在,让我们启动 OpenClaw 并测试它的能力!

在终端运行:

node index.js 

测试案例 1:文件操作

你输入: 在当前目录下创建一个叫 demo.txt 的文件,里面写入 "Hello ZEEKLOG"
OpenClaw:
(后台日志: > OpenClaw is executing: echo “Hello ZEEKLOG” > demo.txt)

文件 demo.txt 已成功创建并写入内容。

测试案例 2:系统查询

你输入: 我想知道我的电脑运行了多久了(uptime)
OpenClaw:
(后台日志: > OpenClaw is executing: uptime)

你的系统运行时间如下:up 3 days, 4:21…

测试案例 3:自我认知与逻辑

你输入: 查看 demo.txt 的内容,并把内容重复三遍输出给我
OpenClaw:
(后台日志: > OpenClaw is executing: cat demo.txt)

好的,内容重复三遍如下:
Hello ZEEKLOG
Hello ZEEKLOG
Hello ZEEKLOG

6. 进阶扩展思路

恭喜!你刚刚用不到 100 行代码,构建了一个拥有系统级操作能力的 AI Agent。这只是一个开始,你可以从以下几个方向继续扩展 OpenClaw:

  1. 增加安全锁:为了防止 AI 发疯执行 rm -rf /,你可以增加一个 confirm 步骤,当检测到危险命令时,先让用户输入 y 确认。
  2. 网络能力:添加一个 fetch_url 工具,让 OpenClaw 可以读取网页内容,实现“联网搜索”。
  3. 持久化记忆:目前重启后 OpenClaw 会失忆。你可以引入简单的 JSON 文件读写,或者向量数据库来保存长期记忆。
  4. 系统级集成:将其打包成 CLI 工具,让它能在任何目录下直接通过 openclaw "帮我整理当前文件夹" 来调用。

7. 总结

AI Agent 的时代正在到来,Local-First(本地优先) 将是保障隐私和效率的重要方向。通过本文的实战,你应该已经理解了 Agent 的核心原理:Prompt Engineering + Function Calling

如果你觉得这篇文章对你有帮助,欢迎点赞收藏!你的支持是我更新的最大动力。

参考资料:OpenAI API DocumentationDeepSeek API DocsNode.js Child Process Documentation

本文由ywy 原创发布于 ZEEKLOG,转载请注明出处。

Read more

GoWeb必备理论

GoWeb必备理论

关于goweb,你不得不知道的知识 若是初学者可以借鉴GoWeb查阅本文。 HTTP状态码: 意义 每个状态码都是,http设计者对“网络通讯”中可能出现的情况的假设、预判。他就相当于现实世界的信号灯,就像大家一遇到404,就知道资源找不到了。一遇到500就知道服务器挂了。这种共识,也就是如今万维网的高效率的基础之一。 http状态码是日常开发,修改bug,的居家必备神器。咱们对常见状态码做了分类。 1、必须掌握的状态码 200 ok 最常见的状态码,代表请求完全正确,比如打开网页、调用api啥的。 301 moved permanently 资源永久迁移(例:访问时a.com会被从定项到b.com) 302 Found (部分资源,临时迁移) 400 Bad request(请求出错,参数缺少什么的..) 401 unauthorized(没有登入) 403 forbidden(

By Ne0inhk
Flutter for OpenHarmony:web 拥抱 Web 标准的桥梁(Wasm GC 与 DOM 互操作) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:web 拥抱 Web 标准的桥梁(Wasm GC 与 DOM 互操作) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 随着 Flutter 3.x 全面拥抱 Wasm(WebAssembly),Dart 团队推出了全新的 package:web 来取代老旧的 dart:html。 package:web 是基于最新的 JS Interop 机制构建的,它不仅性能更好,而且兼容 Wasm GC 标准。 虽然这个库通过名字看是为 “Web” 平台的,但对于 OpenHarmony 开发者来说,了解它有着特殊的意义: 1. 混合开发:鸿蒙原生支持 ArkWeb (WebView),在 Flutter 中通过 JS互操作与 Web 页面交互是常见需求。 2.

By Ne0inhk

前端新手必学:5分钟搞定postcss-px-to-viewport

快速体验 1. 打开 InsCode(快马)平台 https://www.inscode.net 2. 点击'项目生成'按钮,等待项目生成完整后预览效果 输入框内输入如下内容: 请创建一个面向新手的postcss-px-to-viewport教学示例,要求:1. 从创建Vue/React项目开始 2. 分步讲解安装和配置过程 3. 提供最简单的配置示例 4. 包含常见错误排查方法 5. 最终输出一个可运行的demo项目。请使用最基础的配置,并添加大量注释和说明文字。 作为一名前端新手,在开发移动端页面时,最头疼的问题之一就是如何让页面在不同尺寸的设备上都能正常显示。传统的px单位在移动端适配中显得力不从心,这时候就需要用到postcss-px-to-viewport这个神器了。今天我就来分享一下我的学习心得,手把手教你如何快速上手这个工具。 1. 为什么要用postcss-px-to-viewport 在移动端开发中,我们经常需要根据设备宽度来调整元素尺寸。postcss-px-to-viewport可以将px单位自动转换为vw单位(视窗宽度单位),实现真正的响应式布局

By Ne0inhk

OpenClaw Webhook 详解:完整指南

Webhook 是将 OpenClaw 从“聊天助手”快速转变为“响应式系统”的最佳方式。无需等待您主动发送消息,GitHub 可以在 PR 提交时通知 OpenClaw,Stripe 可以在支付失败时通知 OpenClaw,n8n 也可以按计划通知 OpenClaw。OpenClaw 会接收这些传入事件,并将其转换为代理运行或轻量级唤醒操作,然后将结果路由回您实际使用的任何渠道。 本文重点介绍 OpenClaw 网关上的 HTTP Webhook。OpenClaw 中还有另一种东西,在一些文档和配置中也被称为“钩子”。这些是网关内部的事件钩子,当本地生命周期事件触发时运行。它们也很有用,但 Stripe 或 GitHub 与服务器通信的方式并非通过它们。 如果您的 OpenClaw 实例是刚刚部署在 VPS 上,并且您仍然使用 SSH 进行基本操作,那么首先要确保网关稳定,

By Ne0inhk