C# OpenClaw AI Agent 实现

OpenClaw:开源自主智能 Agent 框架,具备工具调用、思考链、任务拆解、多轮交互、函数调用,基于原生 C# .NET8,轻量化本地 Agent,不依赖第三方大模型 SDK,预留对接 OpenAI / 通义千问 / 本地 LLM 接口。

1. 项目结构

plaintext

OpenClawAgent/
├── Core/AgentCore.cs       // Agent核心调度
├── Core/Thought.cs         // 思考链路
├── Tools/ToolBase.cs       // 工具基类
├── Tools/CalcTool.cs       // 示例工具:计算器
├── AgentConfig.cs
└── Program.cs

2. 完整源码

AgentConfig.cs

csharp

运行

namespace OpenClawAgent;

public class AgentConfig
{
    // 最大思考轮次,防止死循环
    public int MaxThinkRound { get; set; } = 8;
    // LLM接口地址,替换成本地Qwen/Ollama/云端API
    public string LlmEndpoint { get; set; } = "http://localhost:11434/api/generate";
    public string ModelName { get; set; } = "qwen:7b";
}

Core/Thought.cs(思维链结构)

csharp

运行

namespace OpenClawAgent.Core;

/// <summary>
/// OpenClaw Agent 思考步骤结构体
/// </summary>
public enum ThinkAction
{
    Answer,     // 直接回答
    CallTool,   // 调用工具
    Continue    // 继续思考
}

public class ThoughtStep
{
    public string Reason { get; set; } = string.Empty;
    public ThinkAction Action { get; set; }
    public string ToolName { get; set; } = string.Empty;
    public Dictionary<string, object> ToolArgs { get; set; } = new();
    public string FinalReply { get; set; } = string.Empty;
}

Tools/ToolBase.cs(工具抽象层)

csharp

运行

namespace OpenClawAgent.Tools;

/// <summary>
/// OpenClaw 可调用工具基类
/// </summary>
public abstract class BaseTool
{
    public abstract string Name { get; }
    public abstract string Description { get; }
    // 参数定义:key=参数名,value=参数说明
    public abstract Dictionary<string, string> ArgsDesc { get; }
    public abstract Task<string> RunAsync(Dictionary<string, object> args);
}

Tools/CalcTool.cs(示例算数工具)

csharp

运行

namespace OpenClawAgent.Tools;

/// <summary>
/// 四则运算工具
/// </summary>
public class CalcTool : BaseTool
{
    public override string Name => "calculator";
    public override string Description => "进行加减乘除数学运算,入参expr为数学表达式字符串";

    public override Dictionary<string, string> ArgsDesc => new()
    {
        { "expr", "数学表达式,例如12+34*5" }
    };

    public override async Task<string> RunAsync(Dictionary<string, object> args)
    {
        await Task.Yield();
        var expr = args["expr"].ToString();
        var result = new System.Data.DataTable().Compute(expr, null);
        return $"计算结果:{result}";
    }
}

Core/AgentCore.cs(Agent 核心引擎,OpenClaw 主体)

csharp

运行

using OpenClawAgent.Tools;
using System.Net.Http.Json;
using System.Text;

namespace OpenClawAgent.Core;

public class OpenClawAgent
{
    private readonly AgentConfig _cfg;
    private readonly List<BaseTool> _tools = new();
    private readonly HttpClient _http = new();

    public OpenClawAgent(AgentConfig cfg)
    {
        _cfg = cfg;
    }

    // 注册可用工具
    public void RegisterTool(BaseTool tool) => _tools.Add(tool);

    // 主入口:用户提问,Agent自主思考+工具调用
    public async Task<string> RunAgentAsync(string userQuery)
    {
        var history = new StringBuilder();
        string userInput = userQuery;

        for (int round = 0; round < _cfg.MaxThinkRound; round++)
        {
            // 1. 构造Prompt:工具描述+历史对话+当前问题,让LLM输出思考结果
            var prompt = BuildPrompt(userInput, history.ToString());
            // 2. 请求LLM生成ThoughtStep
            var think = await GetLlmThinkAsync(prompt);

            switch (think.Action)
            {
                case ThinkAction.Answer:
                    return think.FinalReply;

                case ThinkAction.CallTool:
                    // 查找工具并执行
                    var tool = _tools.FirstOrDefault(x => x.Name == think.ToolName);
                    if (tool == null)
                    {
                        history.AppendLine($"工具{think.ToolName}不存在,重新思考。");
                        continue;
                    }
                    var toolRes = await tool.RunAsync(think.ToolArgs);
                    // 工具结果写入历史,下一轮继续推理
                    history.AppendLine($"【工具{tool.Name}返回】:{toolRes}");
                    break;

                case ThinkAction.Continue:
                    history.AppendLine($"中间推理:{think.Reason}");
                    break;
            }
        }
        return "超出最大思考轮次,任务终止";
    }

    // 拼接系统提示词
    private string BuildPrompt(string query, string historyText)
    {
        var toolInfo = string.Join("\n", _tools.Select(t =>
            $"工具名:{t.Name},说明:{t.Description},参数:{string.Join(";", t.ArgsDesc.Select(p => $"{p.Key}:{p.Value}"))}"));

        return $"""
        你是OpenClaw自主Agent,可选动作:Answer直接回答 / CallTool调用工具 / Continue继续思考
        可用工具列表:
        {toolInfo}
        历史推理记录:
        {historyText}
        用户问题:{query}
        输出JSON格式:{{"Reason":"思考过程","Action":"枚举值","ToolName":"","ToolArgs":{{}},"FinalReply":""}}
        """;
    }

    // 调用Ollama/LLM接口,解析返回为ThoughtStep
    private async Task<ThoughtStep> GetLlmThinkAsync(string prompt)
    {
        var reqObj = new { model = _cfg.ModelName, prompt, stream = false };
        var resp = await _http.PostAsJsonAsync(_cfg.LlmEndpoint, reqObj);
        var json = await resp.Content.ReadFromJsonAsync<OllamaResp>();
        string content = json!.response.Trim();

        // 简易json解析,正式项目换Newtonsoft
        return System.Text.Json.JsonSerializer.Deserialize<ThoughtStep>(content)!;
    }

    private class OllamaResp { public string response { get; set; } = ""; }
}

Program.cs 测试入口

csharp

运行

using OpenClawAgent;
using OpenClawAgent.Core;
using OpenClawAgent.Tools;

// 初始化OpenClaw Agent
var config = new AgentConfig { MaxThinkRound = 5 };
var agent = new OpenClawAgent(config);
// 注册计算器工具
agent.RegisterTool(new CalcTool());

// 用户提问,Agent自动调用计算器
var ans = await agent.RunAgentAsync("帮我算 (125+75)*8÷2");
Console.WriteLine("OpenClaw回答:" + ans);

3. 运行说明

  1. 依赖 Ollama 本地部署 Qwen7b:启动 ollama run qwen:7b,自动监听 11434 端口;
  2. Agent 逻辑:
    • 用户提问 → LLM 思考判断是否需要调用工具
    • 需要则自动匹配工具名、入参 → 执行代码工具
    • 工具结果回传给 LLM,再次推理直到生成最终答案
  3. 扩展:新增工具只需要继承BaseTool实现 RunAsync,调用RegisterTool注册即可(联网查询、文件读写、API 调用)。

4. 扩展方向

  • 增加记忆库(SQLite)实现长期记忆;
  • 增加多 Agent 协作(OpenClaw 集群);
  • 接入 OpenAI/DeepSeek 云端 API 替换 Ollama 地址。
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐