Imported from izz-BLUE/enterprise-ai-copilot (
AGENTS.md). Install upstream withnpx skills add izz-BLUE/enterprise-ai-copilot. Copyright stays with the author.
AGENTS.md
企业级 RAG + Agent 业务流程辅助平台(Java + Python 双服务 + React 前端)。 本文件只保留长期稳定的事实与工作纪律;架构 / API / 配置 / 评估参数等细节 按路径导航到 canonical source,不在此复制。动态状态(branch / commit / 临时配置)一律不写入。
三端职责
- Java Spring Boot(backend-java,:8080):企业业务主系统 —— 用户权限、知识库管理、审计日志、业务流程、业务动作确认
- Python FastAPI(agent-python,:8000):AI Agent 服务 —— RAG、LangGraph Agent、Tool Calling、Prompt 编排
- React + Vite(frontend,:5173):前端界面
关键 invariant
- Java authority boundary:受控业务动作必须经 Java 侧 PendingAction 持久化 + nonce 校验 + 幂等确认才执行,默认关闭;启用后由 Java trusted identity policy 决定,public demo 永久只读;
BUSINESS_ACTIONS_REQUIRE_ADMIN=true仅作为额外 server-side hardening,要求内部请求携带匹配的ADMIN_TOKEN。浏览器管理能力使用已验证 JWT 的role=ADMIN,不携带ADMIN_TOKEN。 - D2 Mock OA 管理边界:管理员审批台只调用 Java
/api/admin/mock-oa/**,由已验证 JWT 的role=ADMIN授权;Java 服务端调用内网 Mock OA,浏览器不接触 Mock OA secret、ADMIN_TOKEN或X-Admin-Token。Mock OA 终态与 Java Expense 终态保持独立,直到 webhook 或 reconciliation 成功收口。 - Python Agent Graph:
/agent/langgraph/chat固定走 Planner-first:safety → planner ⇄ tool_executor → finalize,Planner 拥有规划权、无最终业务执行授权,当前预算受MAX_PLANNER_STEPS=6/MAX_TOOL_CALLS=5收敛。legacy Router-first 图仅作为直接测试/离线兼容实现保留,不是生产运行时选择。Tool Catalog 与 Capability Gate 按可信身份、配置和能力动态收缩可见集合,模型不能自行扩大 Tool 权限:- 始终可见:
rag_answer_tool;employee_id、JAVA_BASE_URL、JAVA_INTERNAL_TOKEN均非空时追加leave_balance_tool/leave_request_tool allow_eval=true时追加:eval_report_toolallow_business_actions=true且employee_id非空时追加:leave_proposal_tool;公开demo身份由 Java 固定为allow_business_actions=false
- 始终可见:
- 可信系统字段边界:
employee_id/business_date/trace_id/ 请求 deadline 由每次请求的 Runtime Context 注入,不属于可保存的AgentState,也不进入 LLMarguments;Planner 决策结构由 Pydantic 严格白名单校验;Tool Executor 独立做权限 / Tool 预算 / 成功签名去重校验。 - P3-1 / P3-2 / P3-3 执行快照边界:Java 基于可信
VerifiedIdentity.userId()与已解析conversationId生成X-Agent-Thread-Id;Python 固定在启动时复用ConnectionPool/PostgresSaver/ 持久化图,节点durability="sync"落盘,DSN 缺失或初始化失败即 fail-closed。Checkpoint 只记录执行现场,不是业务事实或权限来源;Planner-first 新执行保存 strictexecution_recoverymarker,并以 actor scope fingerprint 绑定 employee scope(不保存 raw employee_id);同一 thread 的 exact same unfinished request 通过 latestsnapshot.next、marker/date/actor/capability residue/pending-node/replay-safe 校验后以graph.invoke(None)恢复,重新注入当前 Runtime Context;completed execution、legacy deterministic graph、interrupt、scope 变化与不安全状态不自动恢复。当前权限撤销且 Checkpoint 已有 eval 成功结果或 business proposal material 时 fail-closed;敏感结果产生前的权限变化仍由当前 Capability Gate 生效。Resume 保留当前 execution 的tool_history、计数和 execution_id;P3-2execution_history只保存 travel/invoice 成功步骤的有界CONTEXT_ONLY摘要,Fresh 运行仅在 ACTIVE Memory + task type 匹配时 hydrate,不进入当前 Tool 去重、ExpenseProposalContext 或 Memory Trigger。JavaAgentRuntimeThreadExecutionGuard在 Memory Read 前按最终 runtime thread 串行化完整 Java Agent 生命周期;Python guard 继续保护 recovery inspection 到最终 Checkpoint。 - P3-5A / P3-5B1 / P3-5B2a / P3-5B2b / P3-5B3 WAITING_EXTERNAL 边界:Python 只为已由 Java 成功提交且带本地 ExpenseClaim
request_id的报销确认追加prepare_external_wait → external_wait(interrupt);external wait/result 属于同一 execution,不改变business_action=SUCCEEDED或 Memory terminal。P3-5B2a 中 Mock OA SQLite 先提交 PENDING → APPROVED/REJECTED,再 best-effort 发送不含 status 的 HMAC-SHA256 webhook;Java 只对精确 webhook 路径 permitAll,要求原始 body 签名和不超过 5 分钟的 timestamp,随后 GET Mock OA 权威状态,以幂等且禁止回退的方式更新 ExpenseClaim。P3-5B2b 由低频、限批的 Java reconciliation worker 处理,仅对WAITING_APPROVAL + MOCK_OA + external_request_id做带external_last_checked_at的 due CAS 后权威 GET;provider 关闭或查询失败时保持 fail-closed,Webhook 与 reconciliation 共用同一状态同步路径。P3-5B3 只在 Java ExpenseClaim 终态提交后从持久化 correlation 重建可信 Runtime Context,POST Python external resume,由 Python 使用Command(resume)收口 Graph END;失败不回滚 Java 终态,external_resume_*worker 负责低频限批重试。普通 Chat 不跨过 external interrupt;当前 Java thread guard 仍是单实例进程内边界。BusinessAction 与 Memory terminal 语义不变。 leave_proposal_tool定位:Planner-first 下生成action_proposal或missing_fields(Clarification),不执行写操作;confirmationNonce与PendingAction持久化、状态机、TTL、幂等、权限和最终数据库写入全部在 Java 侧完成。leave_proposal_tool不依赖JAVA_BASE_URL/JAVA_INTERNAL_TOKEN;这两个变量只属于leave_balance_tool/leave_request_tool的 Python → Java 内部只读链路。- Safety Guard Lite 定位(Python safety_node):启发式纵深防御过滤器,不是 authorization / trust / tool permission / business validation 边界;原始用户输入始终原样传给下游。
- RAG / 数据权限边界:数据分目录隔离(data/hr|bank|it 原始知识库 / data/processed 构建产物 / data/eval 评估用例);Python 只做检索与生成,业务数据写操作只能走受控业务动作链路。
- 请求链路:前端 → Java (8080) → Python (8000);普通 RAG 走
/agent/chat,Agent 走/agent/langgraph/chat,业务动作确认走/api/agent/actions/{id}/confirm。 - Phoenix 可观测性边界:
PHOENIX_TRACING默认关闭;启用时以 OpenTelemetry/OpenInference + BatchSpanProcessor 旁路追踪 Python AI 请求,初始化/导出失败不得阻断业务。默认不采集 Prompt、用户输入、检索正文或模型输出;business_trace_id只用于关联定位,不是身份、权限或业务事实来源。现有离线评估仍是回归门禁。 - 公网状态约束:仓库对公网实际运行版本无证据,文档统一表述"仓库部署默认固定 Planner-first;legacy deterministic graph 仅保留给直接测试/离线兼容";公网是否启用受控业务动作以运维
.env为准,本文件不据此做能力宣称。
高频命令
- 启动:agent-python
uv run uvicorn app.main:app --reload --port 8000;backend-java./mvnw spring-boot:run;frontendnpm run dev - 测试:agent-python
uv run pytest;backend-java./mvnw test(含 Testcontainers);frontendnpm run test:e2e - 部署:deploy/docker-compose.prod.yml
文档导航(canonical source)
- 架构细节 → docs/architecture.md;业务动作 → docs/controlled-business-actions.md
- API 契约 → docs/api.md
- 完整配置 → agent-python/.env.example 与 backend-java/src/main/resources/application.properties
- 评估参数与指标 → docs/quality-assurance.md 与 scripts/eval/
项目 Skill 触发导航(SOP 见各 SKILL.md,不复制)
- spring-boot-review:改动/审查 Java Controller、Service、异常处理、API 契约
- fastapi-agent-review:改动/审查 Python Agent 模块、DeepSeek 调用、Java-Python 契约
- rag-llm-architecture:设计/审查 RAG 链路、检索质量、幻觉控制、评估
- project-delivery-check:提交 / 推送 / 发布 / 展示前执行交付门禁
- ai-project-interviewer:面试视角评估本项目
工作纪律
- 最小必要修改:不顺手重构无关代码,不引入无关依赖。
- 不通过跳过测试 / 删除测试 / 降低断言掩盖失败;测试失败先查根因。
- 未经用户授权不 commit / push / reset / clean。
- 可廉价验证的假设(命令、配置、行为)优先执行获取环境反馈,不空想。
- 同一检索目标不要跨工具重复执行(FastCtx 与原生搜索选一)。
- 跨服务契约变更(路由 / 请求响应 / 错误码)必须同步两端与 docs/api.md。
- 安全 / 架构变更后同步更新本文件与 docs/architecture.md;本文件与 CLAUDE.md 并行生效,改动同步维护。