欢迎光临
我们一直在努力

【开源发布】FinchBot (雀翎) - 一个真正灵活的 AI Agent 框架

玄同 765

大语言模型 (LLM) 开发工程师 | 中国传媒大学 · 数字媒体技术(智能交互与游戏设计)

CSDN · 个人主页 | GitHub · Follow


关于作者

  • 深耕领域:大语言模型开发 / RAG 知识库 / AI Agent 落地 / 模型微调
  • 技术栈:Python | RAG (LangChain / Dify + Milvus) | FastAPI + Docker
  • 工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案

「让 AI 交互更智能,让技术落地更高效」 欢迎技术探讨与项目合作,解锁大模型与智能交互的无限可能!


FinchBot (雀翎) – 一个真正灵活的 AI Agent 框架

在这里插入图片描述

作者:玄同765 (xt765) 项目地址:GitHub – FinchBot 国内镜像:Gitee – FinchBot

摘要

FinchBot (雀翎) 是一个轻量级、模块化的 AI Agent 框架,基于 LangChain v1.2 和 LangGraph v1.0 构建。它不是又一个简单的 LLM 封装,而是一个深思熟虑的架构设计,专注于三个核心问题:

  • 如何让 Agent 的能力无限扩展? – 通过技能 (Skill) 和工具 (Tool) 的双层扩展机制
  • 如何让 Agent 拥有真正的记忆? – 通过双层存储架构 + Agentic RAG
  • 如何让 Agent 的行为可定制? – 通过动态提示词文件系统
  • 本文将深入剖析 FinchBot 的架构设计,带你了解一个生产级 Agent 框架的诞生过程。


    一、为什么选择 FinchBot?

    在 AI Agent 框架百花齐放的今天,你可能会问:为什么还需要 FinchBot?

    1.1 现有框架的痛点

    痛点传统方案FinchBot 方案
    扩展困难 需要修改核心代码 继承基类或创建 Markdown 文件
    记忆脆弱 依赖 LLM 上下文窗口 双层持久化存储 + 语义检索
    提示词僵化 硬编码在代码中 文件系统,热加载
    架构过时 基于 LangChain 旧版 API LangChain v1.2 + LangGraph v1.0

    1.2 FinchBot 的设计哲学

    隐私优先 → 本地 Embedding,数据不上云
    模块化 → 每个组件独立可替换
    开发者友好 → 类型安全 + 完善文档
    生产级稳定 → 双重检查锁 + 自动重试 + 超时控制
    开箱即用 → 零配置启动,自动降级,富文本界面

    1.3 开箱即用体验

    FinchBot 将 “开箱即用” 作为核心设计理念——无需复杂配置即可上手:

    三步快速上手:

    # 第一步:配置 API 密钥和默认模型
    uv run finchbot config

    # 第二步:管理你的会话
    uv run finchbot sessions

    # 第三步:开始对话
    uv run finchbot chat

    特性说明
    三步上手 config → sessions → chat,三个命令完成完整工作流程
    环境变量配置 所有配置均可通过环境变量设置(OPENAI_API_KEY、ANTHROPIC_API_KEY 等)
    Rich CLI 界面 全屏键盘导航,↑/↓ 箭头选择,交互式操作
    i18n 国际化 内置中英文支持,自动检测系统语言
    自动降级 网页搜索自动降级:Tavily → Brave → DuckDuckGo
    零配置启动 只需设置 API Key,运行 finchbot chat 即可

    二、记忆架构:双层存储 + Agentic RAG

    FinchBot 实现了先进的双层记忆架构,彻底解决了 LLM 上下文窗口限制和长期记忆遗忘问题。

    2.1 为什么是 Agentic RAG?

    对比维度传统 RAGAgentic RAG (FinchBot)
    检索触发 固定流程 Agent 自主决策
    检索策略 单一向量检索 混合检索 + 权重动态调整
    记忆管理 被动存储 主动 remember/recall/forget
    分类能力 自动分类 + 重要性评分
    更新机制 全量重建 增量同步

    2.2 双层存储架构

    #mermaid-svg-iaPbHEuZ5ILhD8cY{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iaPbHEuZ5ILhD8cY .error-icon{fill:#552222;}#mermaid-svg-iaPbHEuZ5ILhD8cY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iaPbHEuZ5ILhD8cY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .marker.cross{stroke:#333333;}#mermaid-svg-iaPbHEuZ5ILhD8cY svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iaPbHEuZ5ILhD8cY p{margin:0;}#mermaid-svg-iaPbHEuZ5ILhD8cY .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster-label text{fill:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster-label span{color:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster-label span p{background-color:transparent;}#mermaid-svg-iaPbHEuZ5ILhD8cY .label text,#mermaid-svg-iaPbHEuZ5ILhD8cY span{fill:#333;color:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .node rect,#mermaid-svg-iaPbHEuZ5ILhD8cY .node circle,#mermaid-svg-iaPbHEuZ5ILhD8cY .node ellipse,#mermaid-svg-iaPbHEuZ5ILhD8cY .node polygon,#mermaid-svg-iaPbHEuZ5ILhD8cY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .rough-node .label text,#mermaid-svg-iaPbHEuZ5ILhD8cY .node .label text,#mermaid-svg-iaPbHEuZ5ILhD8cY .image-shape .label,#mermaid-svg-iaPbHEuZ5ILhD8cY .icon-shape .label{text-anchor:middle;}#mermaid-svg-iaPbHEuZ5ILhD8cY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .rough-node .label,#mermaid-svg-iaPbHEuZ5ILhD8cY .node .label,#mermaid-svg-iaPbHEuZ5ILhD8cY .image-shape .label,#mermaid-svg-iaPbHEuZ5ILhD8cY .icon-shape .label{text-align:center;}#mermaid-svg-iaPbHEuZ5ILhD8cY .node.clickable{cursor:pointer;}#mermaid-svg-iaPbHEuZ5ILhD8cY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .arrowheadPath{fill:#333333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iaPbHEuZ5ILhD8cY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iaPbHEuZ5ILhD8cY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iaPbHEuZ5ILhD8cY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster text{fill:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY .cluster span{color:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iaPbHEuZ5ILhD8cY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iaPbHEuZ5ILhD8cY rect.text{fill:none;stroke-width:0;}#mermaid-svg-iaPbHEuZ5ILhD8cY .icon-shape,#mermaid-svg-iaPbHEuZ5ILhD8cY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iaPbHEuZ5ILhD8cY .icon-shape p,#mermaid-svg-iaPbHEuZ5ILhD8cY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iaPbHEuZ5ILhD8cY .icon-shape rect,#mermaid-svg-iaPbHEuZ5ILhD8cY .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iaPbHEuZ5ILhD8cY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iaPbHEuZ5ILhD8cY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iaPbHEuZ5ILhD8cY :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    服务层

    存储层

    业务层

    MemoryManager

    SQLiteStore真相源

    VectorMemoryStore语义检索

    RetrievalService混合检索

    ClassificationService自动分类

    ImportanceScorer重要性评分

    DataSyncManager数据同步

    结构化层 (SQLite)

    # 作为唯一真相源 (Source of Truth)
    # 存储内容:完整文本、元数据、分类、重要性、访问日志

    class SQLiteStore:
    async def add_memory(self, content: str, metadata: dict) > str:
    """写入记忆,返回唯一 ID"""

    async def search_memories(self, query: str, ...) > list[MemoryItem]:
    """关键词检索,支持元数据过滤"""

    async def get_stats(self) > dict:
    """获取统计信息"""

    语义层 (Vector Store)

    # 基于 ChromaDB + FastEmbed 本地向量存储
    # 支持自然语言语义搜索

    class VectorMemoryStore:
    async def recall(self, query: str, top_k: int) > list[MemoryItem]:
    """语义检索,返回最相似的 K 条记忆"""

    def _lazy_init(self) > None:
    """后台线程延迟初始化,不阻塞主流程"""

    2.3 混合检索策略

    FinchBot 采用加权 RRF (Weighted Reciprocal Rank Fusion) 策略,结合关键词检索和语义检索:

    class QueryType(StrEnum):
    """查询类型,决定检索权重"""
    KEYWORD_ONLY = "keyword_only" # 纯关键词 (1.0/0.0)
    SEMANTIC_ONLY = "semantic_only" # 纯语义 (0.0/1.0)
    FACTUAL = "factual" # 事实型 (0.8/0.2)
    CONCEPTUAL = "conceptual" # 概念型 (0.2/0.8)
    COMPLEX = "complex" # 复杂型 (0.5/0.5)
    AMBIGUOUS = "ambiguous" # 歧义型 (0.3/0.7)

    RRF 融合算法

    def _weighted_rrf(self, query, keyword_weight, vector_weight, k=60):
    """加权 RRF 融合算法"""
    scores: dict[str, float] = {}

    # 关键词检索结果
    keyword_results = self.sqlite_store.search_memories(query)
    for rank, item in enumerate(keyword_results):
    memory_id = item["id"]
    score = keyword_weight * (1.0 / (k + rank + 1))
    scores[memory_id] = scores.get(memory_id, 0.0) + score

    # 向量检索结果
    vector_results = self.vector_store.recall(query)
    for rank, item in enumerate(vector_results):
    memory_id = item["id"]
    score = vector_weight * (1.0 / (k + rank + 1))
    scores[memory_id] = scores.get(memory_id, 0.0) + score

    # 按融合分数排序
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

    2.4 自动分类与重要性评分

    # 自动分类(基于关键词 + 语义)
    categories = {
    "personal": ["我是", "名字", "年龄", "住址"],
    "preference": ["喜欢", "讨厌", "偏好", "习惯"],
    "work": ["工作", "项目", "任务", "会议"],
    "contact": ["邮箱", "电话", "微信"],
    "goal": ["目标", "计划", "想要"],
    "schedule": ["时间", "日期", "日程"],
    }

    # 重要性评分规则
    IMPORTANCE_RULES = {
    "personal": 0.9, # 个人信息最重要
    "preference": 0.7, # 偏好次之
    "contact": 0.8, # 联系方式重要
    "schedule": 0.6, # 日程中等
    }

    2.5 使用示例

    from finchbot.memory import MemoryManager, QueryType
    from pathlib import Path

    # 初始化
    manager = MemoryManager(Path.home() / ".finchbot" / "workspace")

    # 保存记忆(自动分类 + 重要性评分)
    memory = manager.remember(
    content="用户偏好使用深色主题,喜欢简洁的界面设计",
    category="preference", # 可手动指定,也可自动推断
    importance=0.8
    )

    # 检索记忆 – 语义优先
    results = manager.recall(
    query="用户界面偏好",
    query_type=QueryType.CONCEPTUAL, # 概念型查询
    top_k=5
    )

    # 检索记忆 – 关键词优先
    results = manager.recall(
    query="我的邮箱是多少",
    query_type=QueryType.FACTUAL, # 事实型查询
    top_k=3
    )

    # 删除记忆
    stats = manager.forget("旧邮箱")


    三、动态提示词系统:用户可编辑的 Agent 大脑

    FinchBot 的提示词系统采用文件系统 + 模块化组装的设计,让用户可以自由定制 Agent 的行为。

    3.1 Bootstrap 文件系统

    ~/.finchbot/
    ├── SYSTEM.md # 角色设定
    ├── MEMORY_GUIDE.md # 记忆使用指南
    ├── SOUL.md # 灵魂设定(性格特征)
    ├── AGENT_CONFIG.md # Agent 配置
    └── workspace/
    └── skills/ # 自定义技能

    SYSTEM.md 示例

    # FinchBot (雀翎)

    你是一个轻量级 AI 助手,基于 LangChain Ecosystem 构建。

    ## 角色定位
    你是 FinchBot,一个专业的 AI 助手。

    ## 人称使用规则
    – 用"用户"指代正在与你对话的人
    – 用"我"或"FinchBot"指代你自己
    – 不要使用"我们"、"咱们"等模糊称呼

    ## 工具使用原则
    – 主动使用工具完成任务,不要只是说"我会记住"
    – 当用户说"记住"、"别忘了"等关键词时,立即调用 remember 工具

    3.2 提示词加载流程

    #mermaid-svg-LH7b1AvQkCaqOR3n{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LH7b1AvQkCaqOR3n .error-icon{fill:#552222;}#mermaid-svg-LH7b1AvQkCaqOR3n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LH7b1AvQkCaqOR3n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LH7b1AvQkCaqOR3n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LH7b1AvQkCaqOR3n .marker.cross{stroke:#333333;}#mermaid-svg-LH7b1AvQkCaqOR3n svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LH7b1AvQkCaqOR3n p{margin:0;}#mermaid-svg-LH7b1AvQkCaqOR3n .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster-label text{fill:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster-label span{color:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster-label span p{background-color:transparent;}#mermaid-svg-LH7b1AvQkCaqOR3n .label text,#mermaid-svg-LH7b1AvQkCaqOR3n span{fill:#333;color:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n .node rect,#mermaid-svg-LH7b1AvQkCaqOR3n .node circle,#mermaid-svg-LH7b1AvQkCaqOR3n .node ellipse,#mermaid-svg-LH7b1AvQkCaqOR3n .node polygon,#mermaid-svg-LH7b1AvQkCaqOR3n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LH7b1AvQkCaqOR3n .rough-node .label text,#mermaid-svg-LH7b1AvQkCaqOR3n .node .label text,#mermaid-svg-LH7b1AvQkCaqOR3n .image-shape .label,#mermaid-svg-LH7b1AvQkCaqOR3n .icon-shape .label{text-anchor:middle;}#mermaid-svg-LH7b1AvQkCaqOR3n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LH7b1AvQkCaqOR3n .rough-node .label,#mermaid-svg-LH7b1AvQkCaqOR3n .node .label,#mermaid-svg-LH7b1AvQkCaqOR3n .image-shape .label,#mermaid-svg-LH7b1AvQkCaqOR3n .icon-shape .label{text-align:center;}#mermaid-svg-LH7b1AvQkCaqOR3n .node.clickable{cursor:pointer;}#mermaid-svg-LH7b1AvQkCaqOR3n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LH7b1AvQkCaqOR3n .arrowheadPath{fill:#333333;}#mermaid-svg-LH7b1AvQkCaqOR3n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LH7b1AvQkCaqOR3n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LH7b1AvQkCaqOR3n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LH7b1AvQkCaqOR3n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LH7b1AvQkCaqOR3n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LH7b1AvQkCaqOR3n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster text{fill:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n .cluster span{color:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LH7b1AvQkCaqOR3n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LH7b1AvQkCaqOR3n rect.text{fill:none;stroke-width:0;}#mermaid-svg-LH7b1AvQkCaqOR3n .icon-shape,#mermaid-svg-LH7b1AvQkCaqOR3n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LH7b1AvQkCaqOR3n .icon-shape p,#mermaid-svg-LH7b1AvQkCaqOR3n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LH7b1AvQkCaqOR3n .icon-shape rect,#mermaid-svg-LH7b1AvQkCaqOR3n .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LH7b1AvQkCaqOR3n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LH7b1AvQkCaqOR3n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LH7b1AvQkCaqOR3n :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Agent 启动

    加载 Bootstrap 文件

    SYSTEM.md

    MEMORY_GUIDE.md

    SOUL.md

    AGENT_CONFIG.md

    组装提示词

    加载常驻技能

    构建技能摘要 XML

    生成工具文档

    注入运行时信息

    完整系统提示

    发送给 LLM

    3.3 模块化组装代码

    # context.py – 核心加载逻辑
    def build_system_prompt(self, skill_names, use_cache=True) > str:
    parts = []

    # 1. 加载 Bootstrap 文件
    bootstrap = self._load_bootstrap_files()
    parts.append(bootstrap)

    # 2. 加载常驻技能
    always_skills = self.skills.get_always_skills()
    always_content = self.skills.load_skills_for_context(always_skills)
    parts.append(always_content)

    # 3. 构建技能摘要 (XML 格式)
    skills_summary = self.skills.build_skills_summary()
    parts.append(skills_summary)

    # 4. 生成工具文档
    tools_doc = self.tools_generator.generate_tools_content()
    parts.append(tools_doc)

    return "\\n\\n—\\n\\n".join(parts)

    3.4 运行时信息注入

    # core.py – 运行时信息
    def build_system_prompt(workspace: Path) > str:
    prompt_parts = []

    # … Bootstrap 文件 …

    # 运行时信息
    prompt_parts.append(f"## 当前时间\\n{datetime.now().isoformat()}")
    prompt_parts.append(f"## 运行环境\\n{platform.system()} {platform.release()}")
    prompt_parts.append(f"## 工作目录\\n{workspace}")

    return "\\n\\n".join(prompt_parts)

    3.5 用户定制示例

    用户只需编辑 ~/.finchbot/SYSTEM.md 即可改变 Agent 行为:

    <!– 用户自定义的 SYSTEM.md –>
    # FinchBot (雀翎)

    ## 角色定位
    你是一个专注于 Python 开发的 AI 助手。

    ## 回答风格
    – 代码优先,解释在后
    – 使用中文回答
    – 给出完整可运行的代码示例

    ## 专业领域
    – Python 后端开发
    – FastAPI / Flask
    – 数据处理与分析


    四、技能与工具:无限扩展的 Agent 能力

    FinchBot 的扩展性建立在两个层次上:工具层 (Tool) 和 技能层 (Skill)。

    4.1 工具系统:代码级能力扩展

    工具是 Agent 与外部世界交互的桥梁。FinchBot 提供了 11 个内置工具,并支持轻松扩展。

    工具系统架构

    #mermaid-svg-PdgnMwOva6crB5jr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PdgnMwOva6crB5jr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PdgnMwOva6crB5jr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PdgnMwOva6crB5jr .error-icon{fill:#552222;}#mermaid-svg-PdgnMwOva6crB5jr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PdgnMwOva6crB5jr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PdgnMwOva6crB5jr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PdgnMwOva6crB5jr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PdgnMwOva6crB5jr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PdgnMwOva6crB5jr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PdgnMwOva6crB5jr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PdgnMwOva6crB5jr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PdgnMwOva6crB5jr .marker.cross{stroke:#333333;}#mermaid-svg-PdgnMwOva6crB5jr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PdgnMwOva6crB5jr p{margin:0;}#mermaid-svg-PdgnMwOva6crB5jr .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-PdgnMwOva6crB5jr .cluster-label text{fill:#333;}#mermaid-svg-PdgnMwOva6crB5jr .cluster-label span{color:#333;}#mermaid-svg-PdgnMwOva6crB5jr .cluster-label span p{background-color:transparent;}#mermaid-svg-PdgnMwOva6crB5jr .label text,#mermaid-svg-PdgnMwOva6crB5jr span{fill:#333;color:#333;}#mermaid-svg-PdgnMwOva6crB5jr .node rect,#mermaid-svg-PdgnMwOva6crB5jr .node circle,#mermaid-svg-PdgnMwOva6crB5jr .node ellipse,#mermaid-svg-PdgnMwOva6crB5jr .node polygon,#mermaid-svg-PdgnMwOva6crB5jr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PdgnMwOva6crB5jr .rough-node .label text,#mermaid-svg-PdgnMwOva6crB5jr .node .label text,#mermaid-svg-PdgnMwOva6crB5jr .image-shape .label,#mermaid-svg-PdgnMwOva6crB5jr .icon-shape .label{text-anchor:middle;}#mermaid-svg-PdgnMwOva6crB5jr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PdgnMwOva6crB5jr .rough-node .label,#mermaid-svg-PdgnMwOva6crB5jr .node .label,#mermaid-svg-PdgnMwOva6crB5jr .image-shape .label,#mermaid-svg-PdgnMwOva6crB5jr .icon-shape .label{text-align:center;}#mermaid-svg-PdgnMwOva6crB5jr .node.clickable{cursor:pointer;}#mermaid-svg-PdgnMwOva6crB5jr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PdgnMwOva6crB5jr .arrowheadPath{fill:#333333;}#mermaid-svg-PdgnMwOva6crB5jr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PdgnMwOva6crB5jr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PdgnMwOva6crB5jr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PdgnMwOva6crB5jr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PdgnMwOva6crB5jr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PdgnMwOva6crB5jr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PdgnMwOva6crB5jr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PdgnMwOva6crB5jr .cluster text{fill:#333;}#mermaid-svg-PdgnMwOva6crB5jr .cluster span{color:#333;}#mermaid-svg-PdgnMwOva6crB5jr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PdgnMwOva6crB5jr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PdgnMwOva6crB5jr rect.text{fill:none;stroke-width:0;}#mermaid-svg-PdgnMwOva6crB5jr .icon-shape,#mermaid-svg-PdgnMwOva6crB5jr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PdgnMwOva6crB5jr .icon-shape p,#mermaid-svg-PdgnMwOva6crB5jr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PdgnMwOva6crB5jr .icon-shape rect,#mermaid-svg-PdgnMwOva6crB5jr .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PdgnMwOva6crB5jr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PdgnMwOva6crB5jr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PdgnMwOva6crB5jr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    内置工具 – 11个

    工具注册中心

    自定义扩展

    继承 FinchTool

    注册到 Registry

    ToolRegistry全局注册表

    双重检查锁线程安全

    文件操作read/write/edit/list

    网络能力search/extract

    记忆管理remember/recall/forget

    系统控制exec/session_title

    Agent 调用

    内置工具一览
    类别工具功能
    文件操作 read_file 读取本地文件
    write_file 写入本地文件
    edit_file 编辑文件内容
    list_dir 列出目录内容
    网络能力 web_search 联网搜索 (Tavily/Brave/DDG)
    web_extract 网页内容提取
    记忆管理 remember 主动存储记忆
    recall 检索记忆
    forget 删除/归档记忆
    系统控制 exec 安全执行 Shell 命令
    session_title 管理会话标题
    网页搜索:三引擎降级设计

    FinchBot 的网页搜索工具采用巧妙的三引擎自动降级机制,兼顾灵活性和开箱即用体验:

    优先级引擎API Key特点
    1 Tavily 需要 质量最佳,专为 AI 优化,深度搜索
    2 Brave Search 需要 免费额度大,隐私友好
    3 DuckDuckGo 无需 始终可用,零配置

    工作原理:

  • 如果设置了 TAVILY_API_KEY → 使用 Tavily(质量最佳)
  • 否则如果设置了 BRAVE_API_KEY → 使用 Brave Search
  • 否则 → 使用 DuckDuckGo(无需 API Key,始终可用)
  • 这个设计确保即使没有任何 API Key 配置,网页搜索也能开箱即用!

    会话标题:智能命名,开箱即用

    session_title 工具体现了 FinchBot 的开箱即用理念:

    操作方式说明示例
    自动生成 对话 2-3 轮后,AI 自动根据内容生成标题 “Python 异步编程讨论”
    Agent 修改 告诉 Agent “把会话标题改成 XXX” Agent 调用工具自动修改
    手动重命名 在会话管理器中按 r 键重命名 用户手动输入新标题

    # Agent 调用示例
    session_title(action="set", title="新会话标题")

    # 获取当前标题
    session_title(action="get")

    这个设计让用户无需关心技术细节,无论是自动还是手动,都能轻松管理会话。

    工具注册机制

    # 工具基类定义
    from finchbot.tools.base import FinchTool
    from typing import Any, ClassVar

    class MyCustomTool(FinchTool):
    """自定义工具示例"""

    name: str = "my_custom_tool"
    description: str = "我的自定义工具描述"
    parameters: ClassVar[dict[str, Any]] = {
    "type": "object",
    "properties": {
    "input_text": {
    "type": "string",
    "description": "输入文本"
    }
    },
    "required": ["input_text"]
    }

    def _run(self, input_text: str) > str:
    # 实现你的逻辑
    return f"处理结果: {input_text}"

    双重检查锁定保证线程安全

    # core.py 中的线程安全实现
    def _register_default_tools() > None:
    global _default_tools_registered

    if _default_tools_registered:
    return

    with _tools_registration_lock:
    if _default_tools_registered: # 双重检查
    return
    # 实际注册逻辑…
    _default_tools_registered = True

    4.2 技能系统:用 Markdown 定义 Agent 能力

    技能是 FinchBot 的独特创新——用 Markdown 文件定义 Agent 的能力边界。

    最大特色:Agent 自动创建技能

    FinchBot 内置了 skill-creator 技能,这也是开箱即用理念的体现:

    只需告诉 Agent 你想要什么技能,Agent 就会自动创建好!

    用户: 帮我创建一个翻译技能,可以把中文翻译成英文

    Agent: 好的,我来为你创建翻译技能…
    [调用 skill-creator 技能]
    ✅ 已创建 skills/translator/SKILL.md
    现在你可以直接使用翻译功能了!

    工作流程:

    #mermaid-svg-3ADASVzwYZtBEYku{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3ADASVzwYZtBEYku .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3ADASVzwYZtBEYku .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3ADASVzwYZtBEYku .error-icon{fill:#552222;}#mermaid-svg-3ADASVzwYZtBEYku .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3ADASVzwYZtBEYku .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3ADASVzwYZtBEYku .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3ADASVzwYZtBEYku .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3ADASVzwYZtBEYku .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3ADASVzwYZtBEYku .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3ADASVzwYZtBEYku .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3ADASVzwYZtBEYku .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3ADASVzwYZtBEYku .marker.cross{stroke:#333333;}#mermaid-svg-3ADASVzwYZtBEYku svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3ADASVzwYZtBEYku p{margin:0;}#mermaid-svg-3ADASVzwYZtBEYku .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3ADASVzwYZtBEYku .cluster-label text{fill:#333;}#mermaid-svg-3ADASVzwYZtBEYku .cluster-label span{color:#333;}#mermaid-svg-3ADASVzwYZtBEYku .cluster-label span p{background-color:transparent;}#mermaid-svg-3ADASVzwYZtBEYku .label text,#mermaid-svg-3ADASVzwYZtBEYku span{fill:#333;color:#333;}#mermaid-svg-3ADASVzwYZtBEYku .node rect,#mermaid-svg-3ADASVzwYZtBEYku .node circle,#mermaid-svg-3ADASVzwYZtBEYku .node ellipse,#mermaid-svg-3ADASVzwYZtBEYku .node polygon,#mermaid-svg-3ADASVzwYZtBEYku .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3ADASVzwYZtBEYku .rough-node .label text,#mermaid-svg-3ADASVzwYZtBEYku .node .label text,#mermaid-svg-3ADASVzwYZtBEYku .image-shape .label,#mermaid-svg-3ADASVzwYZtBEYku .icon-shape .label{text-anchor:middle;}#mermaid-svg-3ADASVzwYZtBEYku .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3ADASVzwYZtBEYku .rough-node .label,#mermaid-svg-3ADASVzwYZtBEYku .node .label,#mermaid-svg-3ADASVzwYZtBEYku .image-shape .label,#mermaid-svg-3ADASVzwYZtBEYku .icon-shape .label{text-align:center;}#mermaid-svg-3ADASVzwYZtBEYku .node.clickable{cursor:pointer;}#mermaid-svg-3ADASVzwYZtBEYku .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3ADASVzwYZtBEYku .arrowheadPath{fill:#333333;}#mermaid-svg-3ADASVzwYZtBEYku .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3ADASVzwYZtBEYku .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3ADASVzwYZtBEYku .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3ADASVzwYZtBEYku .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3ADASVzwYZtBEYku .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3ADASVzwYZtBEYku .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3ADASVzwYZtBEYku .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3ADASVzwYZtBEYku .cluster text{fill:#333;}#mermaid-svg-3ADASVzwYZtBEYku .cluster span{color:#333;}#mermaid-svg-3ADASVzwYZtBEYku div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3ADASVzwYZtBEYku .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3ADASVzwYZtBEYku rect.text{fill:none;stroke-width:0;}#mermaid-svg-3ADASVzwYZtBEYku .icon-shape,#mermaid-svg-3ADASVzwYZtBEYku .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3ADASVzwYZtBEYku .icon-shape p,#mermaid-svg-3ADASVzwYZtBEYku .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3ADASVzwYZtBEYku .icon-shape rect,#mermaid-svg-3ADASVzwYZtBEYku .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3ADASVzwYZtBEYku .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3ADASVzwYZtBEYku .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3ADASVzwYZtBEYku :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    用户描述需求

    Agent 理解意图

    调用 skill-creator

    生成 SKILL.md

    技能立即可用

    下次对话自动加载

    无需手动创建文件、无需编写代码,一句话就能扩展 Agent 能力!

    技能文件结构

    skills/
    ├── skill-creator/ # 技能创建器(内置)- 开箱即用的核心
    │ └── SKILL.md
    ├── summarize/ # 智能总结(内置)
    │ └── SKILL.md
    ├── weather/ # 天气查询(内置)
    │ └── SKILL.md
    └── my-custom-skill/ # Agent 自动创建或用户自定义
    └── SKILL.md

    技能定义格式

    <!– skills/weather/SKILL.md –>

    name: weather
    description: 查询当前天气和天气预报(无需 API 密钥)
    metadata:
    finchbot:
    emoji: 🌤️
    always: false
    requires:
    bins: [curl]
    env: []

    # 天气查询技能

    ## 功能说明
    使用 wttr.in 服务查询天气信息…

    ## 使用方式
    当用户询问天气相关问题时…

    技能加载机制

    #mermaid-svg-UMfY3FP71ZKW3y1v{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UMfY3FP71ZKW3y1v .error-icon{fill:#552222;}#mermaid-svg-UMfY3FP71ZKW3y1v .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UMfY3FP71ZKW3y1v .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UMfY3FP71ZKW3y1v .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UMfY3FP71ZKW3y1v .marker.cross{stroke:#333333;}#mermaid-svg-UMfY3FP71ZKW3y1v svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UMfY3FP71ZKW3y1v p{margin:0;}#mermaid-svg-UMfY3FP71ZKW3y1v .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster-label text{fill:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster-label span{color:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster-label span p{background-color:transparent;}#mermaid-svg-UMfY3FP71ZKW3y1v .label text,#mermaid-svg-UMfY3FP71ZKW3y1v span{fill:#333;color:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v .node rect,#mermaid-svg-UMfY3FP71ZKW3y1v .node circle,#mermaid-svg-UMfY3FP71ZKW3y1v .node ellipse,#mermaid-svg-UMfY3FP71ZKW3y1v .node polygon,#mermaid-svg-UMfY3FP71ZKW3y1v .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UMfY3FP71ZKW3y1v .rough-node .label text,#mermaid-svg-UMfY3FP71ZKW3y1v .node .label text,#mermaid-svg-UMfY3FP71ZKW3y1v .image-shape .label,#mermaid-svg-UMfY3FP71ZKW3y1v .icon-shape .label{text-anchor:middle;}#mermaid-svg-UMfY3FP71ZKW3y1v .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UMfY3FP71ZKW3y1v .rough-node .label,#mermaid-svg-UMfY3FP71ZKW3y1v .node .label,#mermaid-svg-UMfY3FP71ZKW3y1v .image-shape .label,#mermaid-svg-UMfY3FP71ZKW3y1v .icon-shape .label{text-align:center;}#mermaid-svg-UMfY3FP71ZKW3y1v .node.clickable{cursor:pointer;}#mermaid-svg-UMfY3FP71ZKW3y1v .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UMfY3FP71ZKW3y1v .arrowheadPath{fill:#333333;}#mermaid-svg-UMfY3FP71ZKW3y1v .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UMfY3FP71ZKW3y1v .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UMfY3FP71ZKW3y1v .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UMfY3FP71ZKW3y1v .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UMfY3FP71ZKW3y1v .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UMfY3FP71ZKW3y1v .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster text{fill:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v .cluster span{color:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UMfY3FP71ZKW3y1v .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UMfY3FP71ZKW3y1v rect.text{fill:none;stroke-width:0;}#mermaid-svg-UMfY3FP71ZKW3y1v .icon-shape,#mermaid-svg-UMfY3FP71ZKW3y1v .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UMfY3FP71ZKW3y1v .icon-shape p,#mermaid-svg-UMfY3FP71ZKW3y1v .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UMfY3FP71ZKW3y1v .icon-shape rect,#mermaid-svg-UMfY3FP71ZKW3y1v .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UMfY3FP71ZKW3y1v .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UMfY3FP71ZKW3y1v .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UMfY3FP71ZKW3y1v :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Agent 启动

    扫描 skills 目录

    工作区技能存在?

    加载工作区技能

    内置技能存在?

    加载内置技能

    跳过

    检查依赖

    依赖满足?

    标记为可用

    标记为不可用

    构建技能摘要

    注入系统提示

    核心设计亮点
    特性说明
    Agent 自动创建 告诉 Agent 需求,自动生成技能文件
    双层技能源 工作区技能优先,内置技能兜底
    依赖检查 自动检查 CLI 工具和环境变量
    缓存失效检测 基于文件修改时间,智能缓存
    渐进式加载 常驻技能优先,按需加载其他

    五、LangChain 1.2 架构实践

    FinchBot 基于 LangChain v1.2 和 LangGraph v1.0 构建,采用最新的 Agent 架构。

    5.1 Agent 创建流程

    from langchain.agents import create_agent
    from langgraph.checkpoint.sqlite import SqliteSaver

    def create_finch_agent(
    model: BaseChatModel,
    workspace: Path,
    tools: Sequence[BaseTool] | None = None,
    use_persistent: bool = True,
    ) > tuple[CompiledStateGraph, SqliteSaver | MemorySaver]:

    # 1. 初始化检查点(持久化状态)
    if use_persistent:
    checkpointer = SqliteSaver.from_conn_string(str(db_path))
    else:
    checkpointer = MemorySaver()

    # 2. 构建系统提示
    system_prompt = build_system_prompt(workspace)

    # 3. 创建 Agent(使用 LangChain 官方 API)
    agent = create_agent(
    model=model,
    tools=list(tools) if tools else None,
    system_prompt=system_prompt,
    checkpointer=checkpointer,
    )

    return agent, checkpointer

    5.2 LangGraph 状态管理

    #mermaid-svg-jqyvL9nZMEe6oyJb{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jqyvL9nZMEe6oyJb .error-icon{fill:#552222;}#mermaid-svg-jqyvL9nZMEe6oyJb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jqyvL9nZMEe6oyJb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jqyvL9nZMEe6oyJb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jqyvL9nZMEe6oyJb .marker.cross{stroke:#333333;}#mermaid-svg-jqyvL9nZMEe6oyJb svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jqyvL9nZMEe6oyJb p{margin:0;}#mermaid-svg-jqyvL9nZMEe6oyJb .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster-label text{fill:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster-label span{color:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster-label span p{background-color:transparent;}#mermaid-svg-jqyvL9nZMEe6oyJb .label text,#mermaid-svg-jqyvL9nZMEe6oyJb span{fill:#333;color:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb .node rect,#mermaid-svg-jqyvL9nZMEe6oyJb .node circle,#mermaid-svg-jqyvL9nZMEe6oyJb .node ellipse,#mermaid-svg-jqyvL9nZMEe6oyJb .node polygon,#mermaid-svg-jqyvL9nZMEe6oyJb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jqyvL9nZMEe6oyJb .rough-node .label text,#mermaid-svg-jqyvL9nZMEe6oyJb .node .label text,#mermaid-svg-jqyvL9nZMEe6oyJb .image-shape .label,#mermaid-svg-jqyvL9nZMEe6oyJb .icon-shape .label{text-anchor:middle;}#mermaid-svg-jqyvL9nZMEe6oyJb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jqyvL9nZMEe6oyJb .rough-node .label,#mermaid-svg-jqyvL9nZMEe6oyJb .node .label,#mermaid-svg-jqyvL9nZMEe6oyJb .image-shape .label,#mermaid-svg-jqyvL9nZMEe6oyJb .icon-shape .label{text-align:center;}#mermaid-svg-jqyvL9nZMEe6oyJb .node.clickable{cursor:pointer;}#mermaid-svg-jqyvL9nZMEe6oyJb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jqyvL9nZMEe6oyJb .arrowheadPath{fill:#333333;}#mermaid-svg-jqyvL9nZMEe6oyJb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jqyvL9nZMEe6oyJb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jqyvL9nZMEe6oyJb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jqyvL9nZMEe6oyJb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jqyvL9nZMEe6oyJb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jqyvL9nZMEe6oyJb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster text{fill:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb .cluster span{color:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jqyvL9nZMEe6oyJb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jqyvL9nZMEe6oyJb rect.text{fill:none;stroke-width:0;}#mermaid-svg-jqyvL9nZMEe6oyJb .icon-shape,#mermaid-svg-jqyvL9nZMEe6oyJb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jqyvL9nZMEe6oyJb .icon-shape p,#mermaid-svg-jqyvL9nZMEe6oyJb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jqyvL9nZMEe6oyJb .icon-shape rect,#mermaid-svg-jqyvL9nZMEe6oyJb .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jqyvL9nZMEe6oyJb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jqyvL9nZMEe6oyJb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jqyvL9nZMEe6oyJb :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    用户输入

    加载 Checkpoint

    构建 Prompt

    LLM 推理

    需要工具?

    生成回复

    执行工具

    保存 Checkpoint

    返回用户

    5.3 持久化检查点

    # 使用上下文管理器确保资源正确释放
    @contextmanager
    def get_sqlite_checkpointer(workspace: Path) > Iterator[SqliteSaver]:
    db_path = workspace / ".finchbot" / "checkpoints.db"
    with SqliteSaver.from_conn_string(str(db_path)) as checkpointer:
    yield checkpointer

    5.4 支持的 LLM 提供商

    提供商模型特点
    OpenAI GPT-5, GPT-5.2, O3-mini 综合能力最强
    Anthropic Claude Sonnet 4.5, Opus 4.6 安全性高,长文本
    DeepSeek DeepSeek Chat, Reasoner 国产,性价比高
    Gemini Gemini 2.5 Flash Google 最新
    Groq Llama 4 Scout/Maverick 极速推理
    Moonshot Kimi K1.5/K2.5 长文本,国产

    六、快速上手

    6.1 最佳实践:三步上手

    # 第一步:配置 API 密钥和默认模型
    uv run finchbot config

    # 第二步:管理你的会话
    uv run finchbot sessions

    # 第三步:开始对话
    uv run finchbot chat

    这三个命令覆盖了 FinchBot 的核心工作流程:

    命令功能说明
    finchbot config 交互式配置 配置 LLM 提供商、API 密钥、默认模型、网页搜索等
    finchbot sessions 会话管理 全屏界面创建、重命名、删除会话,查看会话历史
    finchbot chat 开始对话 启动交互式聊天,自动加载最近活跃的会话

    6.2 安装

    # 克隆仓库
    git clone https://github.com/xt765/finchbot.git
    cd finchbot

    # 使用 uv 安装依赖
    uv sync

    6.3 备选方案:环境变量

    # 或直接设置环境变量
    export OPENAI_API_KEY="your-api-key"
    uv run finchbot chat

    6.4 可选:下载本地嵌入模型

    # 用于记忆系统的语义搜索(可选但推荐)
    uv run finchbot models download

    6.5 让 Agent 创建技能

    # 无需手动创建!直接在对话中告诉 Agent:
    # "帮我创建一个 XXX 技能,可以…"

    # Agent 会自动调用 skill-creator 技能
    # 生成 SKILL.md 文件并立即可用


    七、总结

    FinchBot 不是一个简单的 LLM 封装,而是一个深思熟虑的 Agent 框架设计:

    核心特性设计亮点
    记忆架构 双层存储,Agentic RAG,加权 RRF
    提示词系统 文件系统,热加载,模块化组装
    工具系统 注册表模式,线程安全,11 个内置工具,三引擎降级
    技能系统 Markdown 定义,Agent 自动创建,开箱即用
    架构实践 LangChain v1.2,LangGraph v1.0
    开箱即用 环境变量配置,Rich CLI,i18n,自动降级

    如果你正在寻找一个:

    • ✅ 隐私优先(本地 Embedding)
    • ✅ 真持久化(双层记忆)
    • ✅ 生产级稳定(完善的错误处理)
    • ✅ 灵活扩展(技能 + 工具双层)
    • ✅ 最新架构(LangChain 1.2)
    • ✅ 开箱即用(零配置启动,自动降级)

    的 AI Agent 框架,FinchBot 值得一试。


    相关链接

    • 📦 项目地址: GitHub – FinchBot
    • 📖 文档: FinchBot 文档
    • 💬 问题反馈: GitHub Issues

    如果这个项目对你有帮助,请给个 Star ⭐️

    赞(0)
    未经允许不得转载:171主机测评 » 【开源发布】FinchBot (雀翎) - 一个真正灵活的 AI Agent 框架
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址