AI Agent 找代码:多仓库多技术栈下的代码定位工程

写在前面

大多数 AI 编码助手的演示都从一个隐含前提出发:代码就在眼前,Agent 只需要读它、改它。

但在真实的企业研发环境里,这个前提经常不成立。

一个汽车软件公司的研发体系,可能同时维护着这样的代码结构:Android 应用层的每个功能模块一个独立 Git 仓库(设置、空调、导航......数十个);Android 系统框架层按 AOSP 方式拆成数百个子仓库,靠 repo 工具和 Manifest 管理;QNX 实时系统有自己的 Manifest;MCU 固件又是完全独立的仓库。

当 AI Agent 收到一条"修复蓝牙连接断开的 Bug"的指令时,它面对的第一个问题不是"怎么改代码",而是"代码在哪"。这个问题的难度,被严重低估了。


问题的三个递进层次

层次一:仓库发现(Repo Discovery)

最直观的困难:面对几十上百个仓库,Agent 怎么知道该去哪个?

有团队的做法是给每个仓库写一段自然语言描述,告诉 Agent 这个仓库是做什么的。这是合理的起点,但有几个系统性局限:

  • 自然语言描述难以被精确匹配,尤其是任务描述和仓库描述用了不同的术语时
  • 描述随代码演进容易过时,维护成本持续存在
  • 没有结构化元数据,Agent 无法按技术栈、业务域做过滤
  • 对 AOSP-style 的大型 Manifest 仓库,"这个 Manifest 管了什么"和"这个功能在哪个子仓库"之间,仍有鸿沟

层次二:跨仓库依赖识别(Cross-Repo Dependency)

真实业务需求往往横跨多个技术栈的多个仓库。一个"空调设置温度"的功能可能是这样的链路:

markdown 复制代码
Android 设置 App(应用层仓库)
    ↕ IPC / AIDL
Android 系统服务(框架层子仓库)
    ↕ HAL 接口
BSP HAL 实现(BSP 层子仓库)
    ↕ 底层通信协议
MCU 固件(MCU 仓库)

Agent 如果只找到了应用层仓库,修改了 UI 逻辑,却没有意识到下层接口也需要同步变更,就会产生"本地编译通过、集成测试失败"的不完整修改。

这个问题靠单仓库描述无法解决------需要显式建模仓库间的依赖关系。

层次三:仓库获取与上下文构建(Repo Fetch & Context)

找到仓库之后,Agent 还需要"得到代码"。

对应用层的单仓库,git clone 就够了。但对 AOSP-style 的代码库,流程是:

  1. 获取 Manifest 仓库
  2. 确定这个任务需要哪些子仓库(全量 sync 成本极高,时间、存储、网络都不允许)
  3. 执行 repo sync -c 加上精选的子仓库列表
  4. 理解跨子仓库的代码依赖

这对 Agent 的工具能力要求,远超一个 git clone


解法方向一:结构化 Repo Registry

把当前的自由文本描述升级为结构化的 Repo Registry,每个仓库条目是一个 YAML 对象:

yaml 复制代码
repo_id: android-app-settings
display_name: 设置应用
tech_stack: android-app
component_type: application
business_domains:
  - 系统设置
  - WiFi
  - 蓝牙
  - 显示
fetch_type: git-single
fetch_url: ssh://gerrit.example.com/settings-app
dependencies:
  - android-framework-systemui
  - android-bsp-display-hal
owners:
  - team: android-app-team

结构化的核心价值:Agent 可以按 tech_stackbusiness_domains 做精确过滤,而不是在大量自然语言里做模糊匹配;dependencies 字段为跨仓库联动提供了基础。

跨技术栈依赖图

在 Repo Registry 基础上,显式维护仓库间的依赖关系。当 Agent 定位到一个仓库时,平台自动查询依赖图,提示可能需要同步修改的关联仓库。

依赖关系来源有两种:

  • 手动维护:由了解架构的人标注,准确但有维护成本
  • 从构建系统导出:AOSP 的构建系统知道哪些模块依赖哪些接口,理论上可以半自动提取

标准化仓库获取协议

把"如何获取这个仓库"从自然语言提升为机器可执行的 fetch spec:

yaml 复制代码
fetch_type: repo-manifest
manifest_repo: ssh://gerrit.example.com/platform/manifest
manifest_branch: main
required_projects:
  - platform/frameworks/base
  - platform/packages/apps/Settings
sparse_checkout: true

Agent 调用平台提供的统一 fetch 工具,传入 repo_id,平台根据 fetch spec 完成实际的代码获取操作,屏蔽底层的 git/repo 差异。


解法方向二:全量预置工作区

另一个思路:不改变任何仓库的组织方式,把所有仓库的代码预先同步到 Agent 可以直接访问的共享工作区。Agent 启动时不需要下载,直接在本地搜索和修改。

这个方案解决了两个问题

  • 消除仓库发现问题------所有代码在同一文件系统,搜索工具直接跨栈运行
  • 消除下载等待------代码预置后 Agent 可立即开始工作

但它没有解决 Token 消耗问题。代码在本地 ≠ 代码在 Agent 的上下文窗口里。Agent 仍然需要靠代码搜索工具定位相关文件,选择性地将少量相关代码段加载进上下文。搜索工具的建设需求,在全量预置方案下和多仓库方案下是完全一样的。

另一个反直觉的问题:搜索范围变大后,噪音也会增加。在多仓库方案里,Agent 已经定位到正确仓库后再搜索,候选结果集合小;在全量预置方案里,同一个关键词可能在数百个文件里命中,Agent 的判断负担反而加重。

工程实施的关键

数百 GB 的代码不应该为每个 Agent 实例复制一份。合理的架构是:

markdown 复制代码
只读共享镜像(全量代码)
    ↓ OverlayFS(CoW 文件系统)
Agent 工作区(薄层,只存储写操作的差量)

每个 Agent 实例读代码时零下载成本,写代码时在自己的薄层上隔离,互不干扰。这个架构在 K8s 容器环境下有成熟的实现路径。

提交回原仓库的流程需要专门设计:Agent 完成修改后,平台需要识别哪些文件属于哪个原始仓库,将变更分拆提交,走各自的 Code Review 流程。这不是零成本的。


三种方案的对比

维度 多仓库 + 结构化 Registry 全量预置工作区
仓库发现难度 通过 Registry 改善 完全消除
下载等待 每次任务需要下载 完全消除
跨层搜索 需跨仓库操作 本地直接支持
Token 效率 需代码搜索工具 同左,问题未消除
AOSP 兼容性 完全兼容 完全兼容
存储成本 按需下载 数百 GB,需共享镜像 + OverlayFS
提交回原仓库 自然 需平台做变更分拆
实施难度 低,渐进改善 中,基础设施有成熟方案
推荐程度 主线方案 高频 Agent 任务场景下有价值

核心结论:两个方案都不能绕开"Agent 需要好的代码搜索和导航工具"这个根本需求。


解法方向三:代码知识图谱

无论仓库如何组织,Agent 在代码工作中面临的根本限制是:上下文窗口装不下大型代码库,必须有选择地加载相关代码段。这个"选择"本身就需要消耗 token 来搜索和判断。

代码知识图谱的思路是:提前用静态分析把代码的结构化关系建成数据库,把原本需要 Agent 读大量文件才能推断出来的关系------谁调用了谁、接口在哪里实现、模块间如何依赖------变成可以直接查询的结构化数据。

分层分析,成本可控

不同分析层次的成本差距很大:

分析层次 内容 工具 成本
符号索引 函数/类/变量的定义位置 tree-sitter,速度极快
调用图 哪些函数调用哪些函数 clangd / language server
接口实现映射 AIDL/HIDL 接口与实现的对应关系 静态分析 + 规则
模块依赖图 模块/库级别的依赖关系 构建系统导出
语义向量索引 代码语义的向量表示,支持模糊搜索 embedding 模型

对于几百 GB 的代码,符号索引 + 调用图 + 接口映射这几层,用 tree-sitter 和 clangd 做静态分析,速度是每分钟百万行量级,全量分析可能需要数小时,是一次性的离线成本。

语义向量索引成本较高,建议对语义索引做选择性覆盖:只对公开接口、头文件、关键模块做 embedding,实现文件内部细节按需处理。

高价值查询场景

知识图谱能给出精准答案、节省大量 token 的场景:

  • "这个 AIDL 接口有哪些实现类?" → 接口实现映射直接返回
  • "哪些模块调用了 AudioFlinger::setStreamVolume?" → 调用图直接返回
  • "修改这个 HAL 接口会影响哪些上层模块?" → 依赖图反向查询
  • "这个函数定义在哪个文件的哪一行?" → 符号索引直接返回

这些查询在没有知识图谱时,Agent 需要用 grep 搜索大量文件并推断,消耗大量 token 且结果不一定准确。
对于车载软件的典型场景(App → Framework → HAL → MCU 的跨层分析),知识图谱的价值尤其高------AIDL/HIDL 接口是各层之间的明确契约,静态分析能准确建立"接口定义 → 接口实现 → 接口调用方"的完整图谱,这正是 Agent 做跨层代码修改时最需要的信息。

技术选型参考

功能 推荐工具 理由
C/C++ 符号和调用图 clangd + bear(编译数据库) AOSP 场景最成熟
Java/Kotlin 符号分析 tree-sitter-java 覆盖应用层
多语言符号索引 tree-sitter 支持 C/C++/Java/Kotlin,速度快
图数据存储 Neo4j 或 DGraph 天然适合调用关系查询
语义向量索引 Qdrant + CodeBERT(本地部署) 避免 embedding API 费用
接口实现映射 自定义规则 + AIDL/HIDL 解析 通用工具不理解 Android HAL 语义

特别注意:AIDL 和 HIDL 接口映射建议单独建索引。Android 的跨层接口定义有明确的规范,写专用解析器成本低、准确率高。


一些未解决的问题

仓库元数据的持续维护:Repo Registry 是静态维护的,代码仓库的职责会随项目演进而变化。如何建立机制让仓库描述和实际代码保持同步,是一个尚未解决的问题。理想状态是把这些信息纳入研发平台动态维护,Agent 通过 MCP 等协议向平台查询,而不是维护本地静态文件。

隐性知识的显式化:跨技术栈的依赖关系(尤其是 App 层到 MCU 层的完整调用链)目前主要存在于资深开发者的脑中。把这些隐性知识结构化地写入依赖图,需要各技术栈的专家投入,不是可以自动化解决的问题。

多仓库任务中的 Agent 协作:当一个任务横跨 Android 应用、系统框架、MCU 三个仓库时,这三部分代码改动应该由同一个 Agent 完成,还是由多个专栈 Agent 分别完成再汇合?这涉及到 Agent Platform 的架构设计,目前还没有清晰的答案。


总结

多仓库多技术栈下的代码定位,是 AI Agent 落地企业研发环境时最容易被低估的工程挑战。解决方案可以分三个层次渐进推进:

  1. 结构化 Repo Registry:把自然语言描述升级为机器可处理的 YAML 元数据,显式建立跨仓库依赖关系,是成本最低的起点
  2. 全量预置工作区:消除仓库发现和下载等待,适合 Agent 任务频繁触发的场景,需要 OverlayFS 等基础设施支持
  3. 代码知识图谱:从根本上改变 Agent 获取代码关系的方式,把"读文件推断"变成"查数据库直取"

无论选择哪个方向,有一点是不变的:Agent 定位相关代码段的能力,取决于搜索和导航工具的质量,而不是代码的物理存放位置


欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。

更多实用知识和有趣产品,欢迎访问我的个人主页

相关推荐
贵慜_Derek1 小时前
《从零实现 Agent 系统》连载 20|MCP 与 Code Execution:协议、档位与 Sidecar
人工智能·设计模式·架构
冬奇Lab1 小时前
每日一个开源项目 第124篇:last30days —— 洞察最近30天:跨越信息茧房的 AI Agent 搜索引擎
人工智能·搜索引擎·开源
armwind1 小时前
openISP学习3-AAF— Anti-Aliasing Filter(抗混叠滤波)
人工智能·计算机视觉
hhzz1 小时前
AI数字营销平台会员功能模拟测评:营销组件、数据监测与专家标注实测体验
人工智能
LiuJun2Son1 小时前
Claude Code + Skill 做 UI 的实战工作流
人工智能·ui
wuhen_n1 小时前
RAG 入门:检索增强生成核心原理
前端·人工智能·typescript·langchain·ai编程
继续商行1 小时前
大模型推理优化实战:从KV Cache到流式响应的全链路性能提升
人工智能
冬奇Lab1 小时前
Agent 系列(15):Agent 记忆系统进阶——短期、长期、压缩,三层记忆架构
人工智能·llm·agent
大雨淅淅1 小时前
【机器人】ROS2 机械臂控制(MoveIt2)从入门到实战
人工智能·python·神经网络·学习·算法·机器学习·机器人