惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
罗磊的独立博客
The GitHub Blog
The GitHub Blog
V
V2EX
Last Week in AI
Last Week in AI
博客园 - 聂微东
MyScale Blog
MyScale Blog
美团技术团队
L
LangChain Blog
博客园 - Franky
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
S
SegmentFault 最新的问题
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
量子位
小众软件
小众软件
宝玉的分享
宝玉的分享
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
D
Docker
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日
读:理解 MCP 架构——LLM 直接调 API 与 MCP 协议的对比
2026-05-05 · via 暗无天日

这种做法很简单:你的应用直接调 LLM API,把工具定义塞进每次请求里,自己跑 agent 循环。

┌─────────────────────────-─────────────────────────┐
│  你的应用(单进程)                               │
│                                                   │
│  ┌──────────────┐  tools 定义+messages ┌────────┐ │
│  │ Agent 循环    │ ─────────────────►  │ LLM API│ │
│  │              │  ◄─────────────────  │        │ │
│  └──────┬───────┘   tool_use / 文本    └────────┘ │
│         │ 调用本地函数                            │
│         ▼                                         │
│  ┌──────────────┐                                 │
│  │ executeTool()│ ──► read_pdf, search_pdf        │
│  └──────────────┘   (和你的代码跑在同一进程里)  │
└─────────────────────────────────-─────────────────┘

你在代码里写好每个工具的名字、描述和参数格式(这叫「工具定义」),每次请求 LLM 时把工具定义和用户消息一起发过去。LLM 看到工具定义后,如果判断需要调工具,就返回一个 tool_use 响应(告诉你调哪个工具、传什么参数)。你的代码拿到 tool_use 后,调对应的函数执行,再把执行结果喂回 LLM。LLM 可能继续返回 tool_use=(调更多工具),也可能直接返回最终回答(=end_turn=)。这个「发消息 → 收 =tool_use → 执行工具 → 喂回结果 → 再发消息」的来回过程就是「工具调用循环」,在 Route 1 里你需要自己写代码管这个循环。

工具定义长这样(以 Node.js 为例):

const tools = [
  {
    name: "read_pdf",
    description: "提取 PDF 文件的全部文本",
    input_schema: {
      type: "object",
      properties: {
        path: { type: "string", description: "PDF 文件路径" }
      },
      required: ["path"]
    }
  },
  ];

async function executeTool(name, input) {
  if (name === "read_pdf")   return await extractTextFromPdf(input.path);
  if (name === "search_pdf") return await searchPdfs(input.directory, input.keyword);
  if (name === "list_pdfs")  return await listPdfFiles(input.path);
  throw new Error(`Unknown tool: ${name}`);
}

这种做法的特点是Agent 循环、工具分派、PDF 解析全跑在一个程序的内存空间里,不需要跨进程通信,也不需要额外部署。你只需要 LLM SDK 和一个 PDF 解析库。但这意味着工具和你的应用紧耦合: executeTool() 里硬编码了每个工具的分派逻辑,只有这个应用能用这些 PDF 工具。