首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁

Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁

作者头像
陆业聪
发布2026-05-25 16:48:43
发布2026-05-25 16:48:43
1020
举报

📰 科技要闻

• AI初创公司Hark完成7亿美元融资,英伟达、AMD、英特尔三大芯片巨头罕见同时参投,押注AI Agent基础设施

• 神舟二十三号发射在即,各系统准备就绪,中国空间站进入常态化运营阶段

• 三星半导体员工谈判达成协议,部分工程师年度奖金高达34万美元,芯片人才争夺白热化

• 英国与海湾六国达成贸易协议,巴林工业部长称"里程碑式成就",覆盖科技与能源合作

📚 Android工程师的AI开发实战系列 · 第2/4篇

用Android思维理解RAG、Agent和微调,从移动端老兵到AI开发者的跨界之路

✅ 第1篇:RAG:给大模型装一个靠谱的「本地数据库」——Android工程师秒懂的检索增强生成

👉 第2篇:Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁(本篇)

⏳ 第3篇:微调:让通用大模型变成你的「专属定制ROM」——从AOSP到LoRA的迁移学习

⏳ 第4篇:RAG+Agent+微调组合拳:搭建一个完整的AI驱动Android开发助手

上一篇我们聊了RAG——给大模型接一个"外挂知识库"。当时有读者问我:RAG能让AI"知道"更多东西,但能不能让它"做"更多事情?比如让它自己去查TAPD上的Bug,读一下相关代码,然后帮我写个周报?

说实话,这个问题第一次被问到的时候,我脑子里闪过的画面是:一个Service在后台默默干活,处理完了通过Callback通知你。

然后我意识到——这不就是Agent吗?

Agent到底是个什么东西

先抛开所有花哨的定义。在我看来,Agent就是一个能自己想、自己干的AI系统。普通的ChatGPT对话是"你问一句它答一句",而Agent是"你给它一个目标,它自己拆解步骤、调用工具、处理中间结果,最后给你一个完整的交付物"。

用Android的话来类比:

普通LLM对话

类比 → Activity:用户点一下,响应一下,交互驱动

Agent智能体

类比 → Service + WorkManager:接到任务后自主运行,中间不需要用户干预,完成后回调通知

更准确地说,Agent的演进路径和Android后台任务的演进惊人地相似:

AI领域

Android类比

特点

ChatBot

Activity

一问一答

Chain(链式调用)

IntentService

固定流程

Agent

Service+WM

自主决策

Multi-Agent

多进程IPC

协作分工

ReAct:Agent的Handler消息循环

Agent最核心的运行范式叫ReAct(Reasoning + Acting)。我第一次看到这个概念的时候,直觉反应是:这不就是Handler的消息循环吗?

Android的Handler循环:取消息 → 判断类型 → 分发处理 → 产生新消息 → 继续循环

Agent的ReAct循环:观察环境 → 推理思考 → 选择行动 → 获取结果 → 继续循环

来看一个具体例子。假设你让Agent"帮我查一下项目里最近一周的高优Bug数量":

🤔 Thought: 需要调TAPD接口查Bug

🔧 Action: 调用search_bugs工具

👀 Observation: 返回12条Bug

🤔 Thought: 需要按优先级过滤

✅ Answer: 高优Bug 5个,分别是...

看出来了吗?Agent不是一次就把事情做完的,它是迭代式的——每一步都基于上一步的结果来决定下一步该干什么。就像Handler不断从MessageQueue里取消息处理一样,Agent不断从环境反馈中获取信息,推理下一步动作。

Function Calling:AI的Intent系统

Agent要"干活",就需要工具。这些工具怎么告诉AI呢?答案是Function Calling——我第一次看到这套机制的时候,整个人都精神了:这TMD不就是Intent系统吗?

Android里你要启动一个Activity或Service,需要声明IntentFilter:

代码语言:javascript
复制
// Android IntentFilter声明
<intent-filter>
<action
android:name=
"com.app.SEARCH_BUG"
/>
<data
android:scheme=
"tapd"
android:host=
"bugs"
/>
</intent-filter>

而在Agent的世界里,你要给AI定义一个工具,长这样:

代码语言:javascript
复制
// Function Calling 工具定义
{
"name": "search_bugs",
"description":
"搜索TAPD上的Bug列表",
"parameters": {
"type": "object",
"properties": {
"project_id": {
"type": "string",
"description":
"项目ID"
},
"priority": {
"type": "string",
"enum": [
"high",
"medium",
"low"
]
}
}
}
}

对比一下:

概念

Android

Agent

声明能力

IntentFilter

Tool Schema

传递参数

Bundle/Extra

JSON参数

路由分发

PackageManager

LLM推理

返回结果

onActivityResult

Tool Response

区别在哪?Android的Intent路由是确定性的——PackageManager查注册表,找到匹配的组件就分发。而Agent的路由是概率性的——LLM根据语义理解来选择该调哪个工具。这既是它强大的地方(灵活),也是它坑爹的地方(不稳定)。

实战:用Kotlin写一个开发助手Agent

光说概念没意思,来写代码。我们搭一个能"查Bug→读代码→写周报"的Agent。作为Android工程师,我选择用Kotlin来实现(毕竟这是我们最熟悉的语言):

定义工具接口

代码语言:javascript
复制
// 工具定义,像不像AIDL?
interface AgentTool {
val name: String
val description: String
val parameters:
JsonSchemasuspend fun execute(
args: JsonObject
): ToolResult
}// TAPD Bug查询工具
class SearchBugsTool(
private val tapd:
TapdClient
) : AgentTool {override val name =
"search_bugs"
override val description =
"搜索项目Bug列表"override suspend fun execute(
args: JsonObject
): ToolResult {
val projectId =
args["project_id"]
.asString()
val bugs =
tapd.searchBugs(
projectId
)
return ToolResult(
bugs.toJson()
)
}
}

Agent核心循环

接下来是最关键的部分——Agent的执行循环。我把它写成了一个类似ViewModel的结构,因为逻辑真的很像:

代码语言:javascript
复制
class DevAssistantAgent(
private val llm:
LlmClient,
private val tools:
List<AgentTool>,
private val maxSteps:
Int = 10
) {
// 对话历史=短期记忆
// 类比ViewModel里的State
private val messages =
mutableListOf<
Message>()suspend fun run(
task: String
): String {
messages += Message(
role = "user",
content = task
)repeat(maxSteps) {
// 1.调LLM推理
val resp = llm.chat(
messages,
tools.toSchema()
)// 2.没有工具调用=完成
if (resp.toolCalls
.isEmpty()) {
return resp.content
}// 3.执行工具调用
messages += resp.toMsg()
for (call in
resp.toolCalls) {
val tool =
tools.find {
it.name ==
call.name
} ?: continue
val result =
tool.execute(
call.args
)
messages += Message(
role = "tool",
content =
result.data,
toolCallId =
call.id
)
}
}
return "超过最大步数限制"
}
}

💡 关键洞察:注意到 maxSteps 这个参数了吗?这就是Agent的"ANR超时保护"。没有它,Agent可能会无限循环下去。这和Android设置5秒ANR超时是同一个设计思路——你不能信任任何执行路径总是能正确终止。

Agent的记忆:ViewModel vs Room

Agent有两种记忆,我发现它们完美对应Android的数据持久化层级:

短期记忆(Working Memory):就是当前对话上下文。每轮对话的消息列表,Agent用它来理解"我之前做了什么"。这就像ViewModel里的StateFlow——进程活着就在,进程死了就没了。

长期记忆(Long-term Memory):跨会话持久化的信息。比如"用户偏好用Kotlin"、"项目用的是MVI架构"。这就是Room数据库——需要主动存,重启后还能读。

代码语言:javascript
复制
// Agent记忆系统
class AgentMemory(
private val db:
MemoryDatabase
) {
// 短期=ViewModel State
private val shortTerm =
mutableListOf<
Message>()// 长期=Room持久化
suspend fun remember(
key: String,
value: String
) {
db.memoryDao()
.upsert(
MemoryEntity(
key, value
)
)
}// 检索相关记忆(RAG!)
suspend fun recall(
query: String
): List<Memory> {
return db.memoryDao()
.searchSimilar(
query
)
}
}

看到recall方法了吗?没错,这就是上一篇讲的RAG!Agent的长期记忆检索本质上就是一个RAG系统。第一篇和第二篇在这里串起来了。

多Agent协作:Android多模块通信的翻版

单个Agent能力有限,复杂任务需要多个Agent协作。这像极了Android大型项目的多模块架构——每个模块独立负责一块业务,通过Router或EventBus通信。

我见过的多Agent协作模式,基本能映射到Android的模块通信方案:

协作模式

Android类比

适用场景

主从式(Orchestrator)

ARouter统一路由

有明确主流程

对等协商式

EventBus广播

无中心决策

流水线式

RxJava操作符链

数据逐步加工

竞争式

多Provider优先级

择优选方案

来看一个"主从式"多Agent的实现,用协程写起来非常自然:

代码语言:javascript
复制
// 多Agent编排器
class OrchestratorAgent(
private val workers:
Map<String,
Agent>
) {
suspend fun dispatch(
task: String
): String {
// 1.规划子任务
val plan =
planSubTasks(task)// 2.并发分发
val results =
coroutineScope {
plan.map { sub ->
async {
workers[sub.type]
!!.run(
sub.desc
)
}
}.awaitAll()
}// 3.汇总结果
return synthesize(
results
)
}
}

有没有感觉很像WorkManager的链式任务?beginWith(taskA).then(taskB, taskC).then(finalTask)——先规划,再并发执行,最后汇总。底层思维是完全一样的。

Agent的稳定性:和网络请求容错一模一样

最后聊聊Agent工程化的核心问题——稳定性。这是大部分教程不会讲的,但却是线上跑Agent最头疼的事。

我列几个典型问题和对应的Android容错策略:

幻觉(编造工具调用参数)

Agent可能会编造不存在的参数值,就像用户传了个非法的Intent Extra。解法一样:校验输入

代码语言:javascript
复制
// 工具执行前校验参数
suspend fun safeExecute(
tool: AgentTool,
args: JsonObject
): ToolResult {
// 校验,像Intent参数检查
val validation =
tool.validate(args)
if (!validation.isValid) {
return ToolResult(
error =
"参数错误:${
validation.msg}"
)
}
return try {
withTimeout(
30_000
) {
tool.execute(args)
}
} catch (e: Exception) {
ToolResult(
error = e.message
)
}
}

无限循环(Agent反复调同一个工具)

这就是Agent版的死循环。除了前面提到的maxSteps限制,还可以加"重复检测":

代码语言:javascript
复制
// 检测Agent是否在"转圈"
fun detectLoop(
history:
List<ToolCall>
): Boolean {
val recent =
history.takeLast(3)
// 连续3次调同一工具+同参数
return recent.size == 3
&& recent.distinct()
.size == 1
}

降级策略

这是我觉得最有Android味的一个设计。我们做网络请求的时候不是经常这样吗——先试主接口,失败了降级到缓存,再不行显示兜底UI。Agent一模一样:

代码语言:javascript
复制
// Agent降级策略
suspend fun runWithFallback(
task: String
): String {
return try {
// L1: 完整Agent推理
agent.run(task)
} catch (e: AgentLoopEx) {
// L2: 简化为单步Chain
simpleChain.run(task)
} catch (e: Exception) {
// L3: 降级为纯LLM回答
llm.chat(task)
}
}

Agent框架选型:Hilt vs Koin式的纠结

最后快速过一下主流Agent框架。我对比的维度和当年选DI框架一样——灵活性 vs 上手成本 vs 社区生态

框架

类比

特点

LangChain

Dagger2

生态最全,但重且抽象泄漏多

CrewAI

Hilt

在LangChain之上的高级封装,上手快

AutoGen

Koin

轻量灵活,多Agent对话模型优秀

自研(Kotlin)

手动DI

完全可控,但造轮子成本高

我的建议:如果你只是想快速体验Agent,用CrewAI三五行代码就能跑起来。如果要做生产级别的事情,自己用Kotlin/Python写核心循环+按需接LangChain的工具包是最稳的——就像现在大家基本都是"Hilt注入+手动管理关键组件"一样。

下期预告

这篇讲了Agent的核心思想——自主推理、工具调用、记忆系统、多Agent协作。如果说RAG让AI"知道得多",那Agent让AI"能干的活多"。

但你有没有发现一个问题:不管是RAG还是Agent,我们都在用通用大模型。如果我想让模型更懂我们的业务术语?更适应我们的代码风格?更准确地理解TAPD工单的格式?

下一篇,我们聊微调——让通用大模型变成你的"专属定制ROM"。就像从AOSP出发做一个定制系统,LoRA微调本质上就是在基础模型上叠一层"薄薄的定制补丁",不改原始权重,但效果立竿见影。

到时候见 🤙

📚 Android工程师的AI开发实战系列 · 第2/4篇

用Android思维理解RAG、Agent和微调,从移动端老兵到AI开发者的跨界之路

✅ 第1篇:RAG:给大模型装一个靠谱的「本地数据库」——Android工程师秒懂的检索增强生成

✅ 第2篇:Agent智能体:让AI自己调API干活——从Android Service到AI Agent的思维跃迁(本篇)

⏳ 第3篇:微调:让通用大模型变成你的「专属定制ROM」——从AOSP到LoRA的迁移学习

⏳ 第4篇:RAG+Agent+微调组合拳:搭建一个完整的AI驱动Android开发助手

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陆业聪 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档