Spring AI实战:手撸Text-to-SQL助手Agent工具链开发全解析

基于Spring AI Alibaba Agent Framework实现自然语言转SQL助手及Tool上下文传递技巧
本文基于Spring AI Alibaba Agent Framework,详解如何通过四步Tool工具链(ListTables、GetSchema、VerifyQuery、ExecuteQuery)构建自然语言转SQL助手。重点剖析了Agent开发中Tool上下文传递的核心问题:Stream模式下ThreadLocal失效的根因及正确方案——使用RunnableConfig+ToolContext通过Metadata传递用户信息,避免跨线程数据丢失。
前言
把用户说的大白话自动转成SQL查询语句,这件事在企业级AI应用中需求量极大。本文基于Spring AI Alibaba Agent Framework,手把手拆解如何通过Tool工具链搭建一个自然语言转SQL的小助手,同时深入聊聊Agent开发中Tool上下文传递的核心技巧——这个坑踩过的人都懂。
Tool上下文传递:ThreadLocal的陷阱与正确方案
问题场景
在Agent应用中有一个非常普遍的需求:用户登录后与大模型对话,Tool被调用时需要拿到当前登录用户的信息(比如UserID、UserName)。在传统Spring AI里,我们习惯用InheritableThreadLocal来传递上下文,但在Alibaba Agent Framework中情况完全不同。
结论先行: 同步调用(call方法)中ThreadLocal能正常工作,但在流式请求(stream)中会彻底失效。

为什么Stream模式下ThreadLocal会失效?
要理解这个问题,需要先了解ThreadLocal的本质:它是Java中一种线程局部变量机制,每个线程拥有独立的变量副本,天然实现线程隔离。InheritableThreadLocal是其子类,允许子线程继承父线程的变量值。在传统Servlet同步模型中,一次HTTP请求从头到尾由同一线程处理,ThreadLocal因此成为传递用户上下文的标准手段。然而在响应式/异步编程模型中,一次请求可能跨越多个线程甚至线程池,ThreadLocal的线程绑定特性反而成为陷阱——Spring WebFlux、Project Reactor等框架均有类似问题,通常通过专用Context对象来替代ThreadLocal完成跨异步边界的上下文传递。
根本原因在于线程模型的差异:
- Call模式:大模型调用和Tool执行跑在同一个线程里,
ThreadLocal自然能正常传递 - Stream模式:大模型调用和Tool执行分属不同线程,无论
ThreadLocal还是InheritableThreadLocal都无法跨线程传递数据
还有一个容易忽略的细节:千万不要在ReactAgent的@Bean配置方法中设置ThreadLocal。原因很简单——Bean初始化发生在Spring Boot启动阶段,等用户真正发起请求时早已切换到另一个线程了。
正确方案:RunnableConfig + ToolContext
Alibaba Agent Framework提供了专门的RunnableConfig机制来解决上下文传递问题,核心分两步。
第一步:构建RunnableConfig,在调用Agent时传入
RunnableConfig config = RunnableConfig.builder()
.threadId("sessionId-xxx") // 用于聊天记录隔离
.addMetadata("userId", "xushu") // 自定义元数据
.build();
agent.call(message, config);
第二步:将Tool的Function接口改为BiFunction,接收ToolContext
BiFunction相比Function多接收一个ToolContext参数,这是Alibaba Agent Framework的扩展设计,使工具函数能感知Agent运行时上下文,而不仅仅处理输入参数——这正是解决上下文传递问题的关键接口设计。
BiFunction<InputType, ToolContext, OutputType> toolFunction = (input, toolContext) -> {
RunnableConfig runnableConfig = (RunnableConfig) toolContext.getContext().get(AGENT_CONFIG);
String userId = runnableConfig.getMetadata().get("userId");
// 业务逻辑...
};
Metadata与ThreadId的使用建议
threadId的职责是聊天记录隔离(可以是会话ID或用户ID),而业务数据(用户ID、权限信息等)建议统一走addMetadata传递。这样做更灵活,也避免了与聊天记录隔离维度产生冲突。
ToolContext的隐藏能力
ToolContext不仅能获取自定义元数据,还能访问当前的聊天记录State——这是Alibaba Graph中的核心概念,包含了用户提示词、大模型响应、工具调用参数等完整的对话上下文信息。

Text-to-SQL助手:核心架构设计
Text-to-SQL技术背景
Text-to-SQL是NLP领域的经典任务,目标是将自然语言问题自动转换为结构化查询语言。早期方案依赖规则引擎和语义解析,准确率受限于规则覆盖度。深度学习时代,基于Seq2Seq和Transformer的模型(如IRNet、RATSQL)在Spider等基准数据集上取得突破。大模型时代,GPT-4等模型凭借强大的上下文理解能力,在零样本(zero-shot)条件下即可生成高质量SQL,但仍面临幻觉问题——模型可能生成语法正确但表名/列名错误的SQL。本文的四步工具链正是针对这一痛点设计:通过动态获取真实Schema和样本数据,将数据库结构信息注入模型上下文,从根本上减少幻觉发生。
多路召回的背景知识
在AI应用中,不同数据源各有所长:
| 检索类型 | 最佳数据源 |
|---|---|
| 聚合查询(总数、平均值、最大值) | 关系型数据库 |
| 语义检索 | 向量数据库 |
| 图关系查询 | 图数据库 |
| 关键字检索 | Elasticsearch / Markdown+Grep |
本文聚焦关系型数据库场景,通过Tool工具链将自然语言转换为SQL并执行MySQL查询。
四步Tool工具链设计
整个Text-to-SQL助手的核心是四个自定义Tool,它们组成一条严谨的ReAct迭代链路。ReAct(Reasoning + Acting)是2022年由Google提出的Agent范式,核心思想是让大模型在推理(Thought)和行动(Action)之间交替迭代,每次行动后观察(Observation)结果再决定下一步。与Chain-of-Thought(CoT)纯推理不同,ReAct允许模型调用外部工具,使其能处理需要实时信息的复杂任务。在Text-to-SQL场景中,ReAct的迭代特性尤为关键——模型不需要一次性生成完美SQL,而是通过多轮工具调用逐步收集信息、验证、修正,最终得到可执行的查询语句:
- ListTables Tool —— 获取数据库中所有表名
- GetSchema Tool —— 获取目标表的结构定义和样本数据
- VerifyQuery Tool —— 借助大模型检验生成的SQL语法是否合法
- ExecuteQuery Tool —— 执行最终的SQL查询并返回结果

实战代码解析
ReactAgent配置详解
通过系统提示词明确指导大模型按顺序调用四个Tool,并使用FunctionToolCallback方式绑定工具:
@Bean
public ReactAgent textToSqlAgent() {
return ReactAgent.builder()
.systemPrompt("你是一个Text-to-SQL助手,请按以下步骤执行...")
.tools(listTablesTool, getSchemaTool, verifyQueryTool, executeQueryTool)
.build();
}
Spring AI中Tool的注册方式主要有两种:动态绑定(运行时根据请求动态加载工具)和静态绑定(编译期确定、随Bean初始化注册)。选择FunctionToolCallback静态绑定方式的理由是:它将Java函数(Function/BiFunction)包装为大模型可调用的工具描述,包含工具名称、功能描述、输入参数的JSON Schema等元信息,大模型通过这些描述决定何时调用哪个工具。这些Tool数量固定、编译期就能确定逻辑、且是应用运行的基础组件——完全符合静态绑定的适用场景。
各Tool核心逻辑拆解
ListTables Tool: 通过JdbcTemplate执行SHOW TABLES获取所有表名,返回给大模型做推理定位。
**Get
相关推荐
教程攻略Cursor+Codex双IDE协同:开源项目二开实战方法论
基于实战经验总结的开源项目二次开发完整方法论,详解Cursor+Codex双IDE协同工作流,涵盖二开七环节、MVP验证、AI读源码技巧,帮助开发者三天跑通项目、两周完成业务集成。
教程攻略Cursor多Agent实战:50分钟搭建Next.js全栈博客
使用Cursor IDE多Agent协作模式,50分钟内从零搭建全栈博客。涵盖Next.js、Clerk认证、Supabase数据库集成,详解4个AI Agent分阶段开发流程与关键避坑经验。
教程攻略从零搭建AI软件工厂:Cursor工程师的多Agent协作实战经验
Cursor工程师Eric分享AI软件工厂构建实战:从自动化六层级、护栏设计、并行Agent管理到规模化扩展,详解如何用多Agent协作实现7×24小时高效软件开发。