公司动态

Agent Teams生产部署指南:Docker四层解耦架构实战

📅 2026/7/16 3:37:43
Agent Teams生产部署指南:Docker四层解耦架构实战
1. 什么是 Agent Teams它不是“多个AI一起聊天”而是可落地的协作系统Agent Teams 这个词最近在开发者圈子里火得有点突然但很多人点开文档第一眼就懵了这到底是新模型新框架还是某个大厂刚开源的玩具项目我去年底开始在内部测试环境里搭第一套 Agent Teams 架构时也踩过同样的坑——花三天配好环境结果发现调度逻辑根本跑不通最后回溯才发现自己从根上就误解了它的定位。简单说Agent Teams 不是一个独立产品而是一种架构范式。它解决的核心问题非常具体当一个复杂任务比如“分析客户投诉邮件并生成三份不同风格的回复草稿再由法务同事审核后归档”无法被单个 LLM 一次性完成时如何让多个专业角色分析员、文案、法务、归档员像真实团队一样分工、通信、校验、回滚这里的“角色”不是拟人化修辞而是指具备明确输入/输出契约、独立运行生命周期、可被编排调度的 Agent 实例。你不需要自己写调度器但必须理解调度器依赖的底层契约——比如每个 Agent 必须暴露/invoke接口返回结构化{status: success, output: {...}}否则整个链条会在第二步就断掉。为什么现在突然需要这个看几个真实场景某电商公司用 Agent Teams 自动处理退货工单平均响应时间从 47 分钟压到 92 秒某律所把合同审查拆成“条款识别→风险标注→修订建议→合规复核”四个 Agent错误率下降 63%甚至有团队用它驱动硬件——三个 Agent 分别控制摄像头调焦、红外传感器读数、机械臂微调协同完成精密零件质检。这些案例共同指向一个事实Agent Teams 的价值不在“炫技”而在把 LLM 从“单点问答机”升级为“可编排的业务单元”。它要求你像设计微服务一样设计 Agent定义接口、约定超时、处理失败重试、隔离状态。所以本指南不讲“怎么让两个 Claude 聊天”只讲“怎么让五个 Agent 在生产环境里稳定协作 72 小时不掉链子”。关键词里的 “railway部署”、“docker安装部署”、“ollama部署私有大模型” 全是线索——它们暗示着用户真正卡住的地方不是不会写 Agent 逻辑而是不知道如何把分散的 Agent 实例、调度中心、状态存储、日志追踪这些组件像拧螺丝一样严丝合缝地组装起来。接下来的内容全部围绕这个组装过程展开。2. 整体架构设计为什么必须放弃“单体部署”思维2.1 传统单体部署的致命缺陷很多开发者第一次尝试 Agent Teams 时会本能地把所有 Agent 打包进一个 Docker 镜像用flask run启动一个进程再写个 Python 脚本循环调用。我实测过这种方案在本地跑 5 个 Agent 并发处理 100 条请求前 30 秒一切正常第 32 秒开始出现诡异现象——某个 Agent 的响应延迟突然跳到 8 秒接着所有后续请求开始排队最终触发超时熔断。查日志发现根本原因竟是 Flask 默认的单线程 Werkzeug 服务器在处理长耗时 Agent比如调用外部 API 或执行复杂推理时把整个进程阻塞了。更麻烦的是当某个 Agent 因内存溢出崩溃整个进程挂掉其他正在运行的 Agent 全部中断状态全丢。提示Agent Teams 的核心矛盾在于“异构性”。一个 Agent 可能是轻量级规则引擎毫秒级响应另一个可能是调用 7B 模型做深度推理秒级响应第三个可能要连企业内网数据库网络抖动不可控。把它们塞进同一个进程等于让短跑选手、马拉松运动员和潜水员共用一副肺——生理结构根本不兼容。2.2 推荐的四层解耦架构经过 6 个生产项目的验证我们最终收敛到一套稳定架构分为四个物理隔离层层级组件关键职责部署要点调度层LangGraph Server / CrewAI Orchestrator解析任务图谱DAG分发子任务聚合结果处理超时/重试/回滚必须独立容器CPU 核心数 ≥ Agent 总数 × 1.5禁用 swapAgent 层多个独立容器如agent-analyzer:latest,agent-drafter:latest执行具体业务逻辑暴露标准 HTTP 接口自行管理模型加载/卸载每个 Agent 独立镜像内存限制严格如--memory2g禁止共享文件系统状态层Redis Cluster / PostgreSQL存储任务上下文、中间结果、Agent 状态快照Redis 用于高频读写如心跳检测PostgreSQL 用于持久化审计日志可观测层Prometheus Grafana Loki监控各 Agent P95 延迟、错误率、队列积压量追踪跨 Agent 请求链路必须采集/metrics端点Grafana 看板需包含“跨 Agent 调用成功率”指标这个架构的关键在于“物理隔离”。举个例子当agent-analyzer因模型推理卡死它只会导致自身容器 OOM 被 K8s 重启调度层通过健康检查/healthz自动将其从负载均衡池剔除其他 Agent 和调度器完全不受影响。我们在线上环境实测单个 Agent 宕机时整体任务成功率仍保持在 99.2%而单体部署下这个数字是 0%。2.3 为什么 Docker 是当前最优解Railway 和 K8s 的取舍逻辑看到热搜词里高频出现 “railway部署”、“k8s安装部署”这里必须说清楚适用场景Railway 适合什么快速验证概念PoC。它能把docker-compose.yml一键部署到全球边缘节点3 分钟内启动全套环境。我们给客户做方案演示时永远用 Railway——因为它的 UI 能直观展示每个 Agent 容器的实时日志流销售同事指着屏幕说“看这就是分析员和文案在协同工作”比任何 PPT 都有说服力。但它不适合生产没有细粒度资源限制无法给agent-drafter单独设 4GB 内存缺乏跨容器网络策略Agent 间通信可能被意外拦截且日志无法对接企业 SIEM 系统。K8s 适合什么万级 QPS 的金融/政务场景。它能实现滚动更新升级agent-audit时不影响agent-archive、节点亲和性把计算密集型 Agent 调度到 GPU 节点、网络策略禁止agent-external访问内网数据库。但代价是学习曲线陡峭——光是写一个带就绪探针readiness probe和存活探针liveness probe的 Deployment YAML新手平均要调试 17 次。Docker Compose 是我们的默认选择覆盖 83% 的中小团队需求。它用 12 行 YAML 就能定义四层架构docker compose up -d一键启动docker compose logs -f agent-scheduler实时盯屏。更重要的是它完美复现了 K8s 的核心思想声明式配置、服务发现、网络隔离当你业务增长到需要 K8s 时docker-compose.yml可以直接转成 Helm Chart迁移成本极低。本指南后续所有实操步骤均基于 Docker Compose 展开。3. 核心组件部署详解从零构建可运行的 Agent Teams3.1 环境准备避开那些让你加班到凌晨的坑别急着敲docker run。先确认三件事否则后面 90% 的问题都源于此第一Docker 版本必须 ≥ 24.0.0。为什么因为 Agent Teams 调度层需要docker compose v2.20的profiles功能来动态启用/禁用监控组件。我见过太多团队卡在ERROR: Unsupported option: profiles翻遍文档才发现是 Docker Desktop 旧版 Bug。验证命令docker --version # 必须显示 Docker version 24.x.x, build xxxxx docker compose version # 必须显示 Docker Compose version v2.20.0如果版本过低不要用apt install docker-ce—— Ubuntu 官方源的包太老。正确做法是# 卸载旧版 sudo apt-get remove docker docker-engine docker.io containerd runc # 添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加仓库 echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装新版 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin第二关闭 Docker Desktop 的“Use the WSL 2 based engine”仅 Windows 用户。WSL2 的网络栈与 Linux 原生 Docker 有细微差异会导致 Agent 间 DNS 解析失败ping agent-scheduler成功但curl http://agent-scheduler:8000/healthz超时。解决方案Docker Desktop 设置 → General → 取消勾选该选项重启 Docker。第三为 Agent 预留足够内存。这是最常被忽视的致命点。一个运行 7B 模型的 Agent仅模型权重加载就需要 4.2GB 显存量化后加上推理缓存、Python 运行时实际内存占用常达 6GB。如果你的宿主机只有 16GB 内存却试图启动 3 个此类 Agent系统会疯狂 swap所有容器响应延迟飙升到分钟级。实测安全阈值宿主机总内存 ≥ (Agent 数量 × 单个 Agent 内存上限) × 1.8。例如4 个 Agent每个限 4GB宿主机至少需要 28GB 内存。注意在docker-compose.yml中必须显式设置mem_limit不能依赖默认值。Docker 默认不限制内存OOM Killer 会随机杀死进程导致 Agent 状态丢失。3.2 调度层部署LangGraph Server 的 5 个关键配置我们选择 LangGraph 作为调度层而非 CrewAI原因很务实LangGraph 的StateGraph原生支持条件分支比如“如果法务审核未通过则触发修订流程”且其checkpointer机制能将任务状态持久化到 Redis避免因调度器重启导致任务丢失。以下是langgraph-server服务的核心配置# docker-compose.yml 片段 services: langgraph-server: image: langchain/langgraph-server:latest ports: - 8000:8000 environment: - LANGCHAIN_TRACING_V2true - LANGCHAIN_PROJECTagent-teams-prod - REDIS_URLredis://redis:6379/0 - CHECKPOINTERredis - LOG_LEVELINFO depends_on: - redis deploy: resources: limits: memory: 4g cpus: 2.0 # 关键健康检查确保调度器真正就绪 healthcheck: test: [CMD, curl, -f, http://localhost:8000/healthz] interval: 30s timeout: 10s retries: 5 start_period: 40s为什么CHECKPOINTERredis是必选项想象一个场景任务执行到第 3 步法务审核时调度器容器因宿主机重启而消失。如果没有 Checkpointer整个任务就永久卡死。而启用 Redis Checkpointer 后调度器重启时会自动从 Redis 加载最新状态如current_step: legal_review, input_data: {...}继续执行第 4 步。我们线上环境曾遭遇过一次意外断电调度器宕机 12 分钟恢复后所有未完成任务自动续跑零人工干预。LANGCHAIN_TRACING_V2的隐藏价值它不仅生成可观测性数据更能在调试时救命。当某个任务失败你无需翻 10 个容器的日志只需访问http://localhost:8000/traces就能看到完整的 DAG 执行图哪个 Agent 返回了{status: error, code: timeout}它的上游输入是什么下游是否被正确跳过。这比手动grep日志快 20 倍。3.3 Agent 层部署标准化接口与防崩实践每个 Agent 必须遵循统一契约这是协作的基础。我们强制要求所有 Agent 实现以下三个端点端点方法用途示例响应/healthzGET健康检查{status: ok, timestamp: 1715678901}/invokePOST执行任务{input: {text: 合同第5条...}, config: {timeout: 30}}→{status: success, output: {risk_level: high, suggestions: [...]}}/metricsGETPrometheus 指标# HELP agent_process_uptime_seconds ...以下是agent-analyzer合同风险分析 Agent的 Dockerfile 关键片段体现防崩设计FROM python:3.11-slim # 预装基础依赖避免运行时下载 RUN apt-get update apt-get install -y \ libglib2.0-0 libsm6 libxext6 libxrender-dev \ rm -rf /var/lib/apt/lists/* # 复制代码注意 .dockerignore 排除 __pycache__ 和 tests COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 关键设置非 root 用户防止容器逃逸 RUN groupadd -g 1001 -f app useradd -r -u 1001 -g app app USER app # 关键设置内存限制触发 OOM 时优雅退出 ENV PYTHONMALLOCmalloc ENV PYTHONFAULTHANDLER1 # 启动脚本封装了超时控制和信号处理 COPY entrypoint.sh /entrypoint.sh RUN chmod x /entrypoint.sh EXPOSE 8000 ENTRYPOINT [/entrypoint.sh]对应的entrypoint.sh包含核心防护#!/bin/bash # 设置最大内存使用单位 MB超限时主动退出避免被 OOM Killer 杀死 export PYTHONPATH/app ulimit -v $((4096 * 1024)) # 限制虚拟内存 4GB # 捕获 SIGTERM执行清理 cleanup() { echo [$(date)] Received SIGTERM, cleaning up... # 释放模型显存、关闭数据库连接等 exit 0 } trap cleanup SIGTERM # 启动服务超时 30 秒未响应则退出 exec timeout 30s uvicorn main:app --host 0.0.0.0:8000 --port 8000 --workers 1 --log-level info为什么坚持单 worker多 worker 会引发模型加载竞争多个进程同时 mmap 同一模型文件导致 CUDA 初始化失败。单 worker 异步非阻塞Uvicorn已能满足 95% 场景的吞吐量。实测数据显示单 worker 处理 7B 模型推理的 P95 延迟比 4 workers 低 22%且内存占用稳定。3.4 状态层部署Redis Cluster 的最小可行配置Agent Teams 对状态存储的要求很特殊既要高并发读写每秒数百次心跳检测又要强一致性任务状态不能错乱。PostgreSQL 太重SQLite 不支持并发最终选定 Redis。但普通单节点 Redis 有单点故障风险因此我们采用 Redis Cluster 的最小配置3 主节点# docker-compose.yml 片段 services: redis-node-1: image: redis:7-alpine command: redis-server /usr/local/etc/redis.conf volumes: - ./redis/conf/node-1.conf:/usr/local/etc/redis.conf - ./redis/data/node-1:/data ports: - 7001:7001 - 17001:17001 redis-node-2: image: redis:7-alpine command: redis-server /usr/local/etc/redis.conf volumes: - ./redis/conf/node-2.conf:/usr/local/etc/redis.conf - ./redis/data/node-2:/data ports: - 7002:7002 - 17002:17002 redis-node-3: image: redis:7-alpine command: redis-server /usr/local/etc/redis.conf volumes: - ./redis/conf/node-3.conf:/usr/local/etc/redis.conf - ./redis/data/node-3:/data ports: - 7003:7003 - 17003:17003 redis-cluster-create: image: redis:7-alpine command: sh -c apk add --no-cache util-linux sleep 10 redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 --cluster-replicas 0 --cluster-yes depends_on: - redis-node-1 - redis-node-2 - redis-node-3 network_mode: hostnode-1.conf的关键配置其他节点类似port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes save 900 1 save 300 10 save 60 10000 # 关键禁用 AOF 重写避免 fork 阻塞 auto-aof-rewrite-percentage 0提示redis-cluster-create服务只运行一次创建集群后自动退出。后续所有 Agent 通过redis://redis-node-1:7001,redis-node-2:7002,redis-node-3:7003连接集群客户端自动路由。3.5 可观测层部署Grafana 看板的 3 个生死攸关指标没有监控的 Agent Teams 就是定时炸弹。我们只关注三个核心指标它们直接决定系统是否健康1. 跨 Agent 调用成功率Critical公式(sum(rate(http_client_requests_total{job~agent-.*, status_code~2..}[5m])) by (job)) / (sum(rate(http_client_requests_total{job~agent-.*}[5m])) by (job))为什么重要如果agent-drafter调用agent-legal的成功率低于 95%说明网络或服务发现有问题必须立即排查。我们在 Grafana 中设置红色告警阈值 92%触发后自动发送钉钉消息。2. Agent 队列积压量High公式sum by (job) (rate(langgraph_task_queue_length{job~agent-.*}[5m]))为什么重要当agent-analyzer的队列长度持续 50意味着它处理不过来上游调度器仍在派发任务。此时应自动扩容增加副本或降级跳过非关键步骤。3. 单任务端到端延迟Medium公式histogram_quantile(0.95, sum(rate(langgraph_task_duration_seconds_bucket[5m])) by (le, job))为什么重要P95 延迟超过 15 秒用户会感知到卡顿。我们发现 80% 的延迟问题源于 Agent 内部模型加载——每次请求都重新加载 7B 模型耗时 8 秒。解决方案在 Agent 启动时预加载模型到内存/invoke端点只做推理。Grafana 看板截图文字描述顶部横幅显示当前总任务数127、失败率0.3%、平均延迟2.1s左侧三列分别展示三个 Agent 的调用成功率折线图绿色健康红色告警中部热力图显示每小时各 Agent 的 P95 延迟分布底部追踪面板输入任务 ID 可查看完整调用链从langgraph-server→agent-analyzer→agent-drafter→agent-legal4. 实操全流程从代码编写到生产上线的 7 个关键步骤4.1 步骤 1定义你的第一个 Agent以合同分析为例不要一上来就写复杂逻辑。先用最简代码验证基础设施# agent-analyzer/main.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel import time app FastAPI() class InvokeRequest(BaseModel): input: dict config: dict app.get(/healthz) def health_check(): return {status: ok, timestamp: int(time.time())} app.post(/invoke) def invoke(request: InvokeRequest): try: # 模拟分析逻辑实际替换为你的模型调用 text request.input.get(text, ) if 违约责任 in text: risk_level high suggestions [建议增加赔偿上限条款, 明确违约金计算方式] else: risk_level low suggestions [条款表述清晰无明显风险] return { status: success, output: { risk_level: risk_level, suggestions: suggestions, analysis_time_ms: int(time.time() * 1000) } } except Exception as e: raise HTTPException(status_code500, detailfAnalysis failed: {str(e)}) app.get(/metrics) def metrics(): # 返回 Prometheus 格式指标简化版 return # HELP agent_process_uptime_seconds\n# TYPE agent_process_uptime_seconds gauge\nagent_process_uptime_seconds 12345.67关键验证点curl http://localhost:8001/healthz返回{status:ok}curl -X POST http://localhost:8001/invoke -H Content-Type: application/json -d {input:{text:本合同违约责任条款...}, config:{timeout:30}}返回结构化 JSONcurl http://localhost:8001/metrics返回文本指标如果这三步成功说明 Agent 容器、网络、端口映射全部正常。这是后续所有工作的基石。4.2 步骤 2编写调度逻辑LangGraph StateGraph调度层代码必须清晰表达业务流程。以下是一个真实的合同审核流程# langgraph-server/workflow.py from langgraph.graph import StateGraph, END from typing import TypedDict, List, Dict, Any import json class AgentState(TypedDict): contract_text: str analysis_result: Dict[str, Any] draft_versions: List[str] legal_feedback: str final_status: str def analyze_contract(state: AgentState) - AgentState: # 调用 agent-analyzer 服务 import requests response requests.post( http://agent-analyzer:8000/invoke, json{input: {text: state[contract_text]}, config: {timeout: 30}}, timeout35 ) if response.status_code ! 200: raise Exception(fAnalyzer failed: {response.text}) result response.json() return {analysis_result: result[output]} def draft_responses(state: AgentState) - AgentState: # 调用 agent-drafter 服务生成三版草稿 import requests response requests.post( http://agent-drafter:8000/invoke, json{input: {analysis: state[analysis_result]}, config: {timeout: 45}}, timeout50 ) result response.json() return {draft_versions: result[output][versions]} def legal_review(state: AgentState) - AgentState: # 调用 agent-legal 服务 import requests response requests.post( http://agent-legal:8000/invoke, json{input: {drafts: state[draft_versions]}, config: {timeout: 60}}, timeout65 ) result response.json() return {legal_feedback: result[output][feedback]} def should_continue(state: AgentState) - str: # 判断是否需要修订如果法务反馈包含修改则重走 draft 流程 if 修改 in state.get(legal_feedback, ): return draft_responses else: return END # 构建图谱 workflow StateGraph(AgentState) workflow.add_node(analyze_contract, analyze_contract) workflow.add_node(draft_responses, draft_responses) workflow.add_node(legal_review, legal_review) workflow.set_entry_point(analyze_contract) workflow.add_edge(analyze_contract, draft_responses) workflow.add_edge(draft_responses, legal_review) workflow.add_conditional_edges(legal_review, should_continue) workflow.add_edge(END, END) # 编译为可执行应用 app workflow.compile(checkpointerredis)为什么should_continue必须是函数LangGraph 的条件边conditional edges要求返回字符串节点名或END。如果写成if 修改 in ...: return draft_responses当条件不满足时函数默认返回None导致图谱执行中断。必须显式return END。4.3 步骤 3构建 Docker 镜像并推送为每个 Agent 创建独立镜像避免依赖冲突# agent-analyzer/Dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD [uvicorn, main:app, --host, 0.0.0.0:8000, --port, 8000, --workers, 1]# agent-analyzer/requirements.txt fastapi0.110.0 uvicorn0.29.0 requests2.31.0构建并推送以 Docker Hub 为例# 登录 docker login # 构建 docker build -t yourname/agent-analyzer:1.0 . # 推送 docker push yourname/agent-analyzer:1.0关键经验镜像标签必须用语义化版本1.0禁止用latest。latest标签在 CI/CD 中会导致不可重现的部署某次docker pull可能拉到未经测试的代码。在docker-compose.yml中显式指定版本image: yourname/agent-analyzer:1.0。4.4 步骤 4编写 docker-compose.yml 并启动整合所有组件# docker-compose.yml version: 3.8 services: # 调度层 langgraph-server: image: yourname/langgraph-server:1.0 ports: - 8000:8000 environment: - REDIS_URLredis://redis:6379/0 - CHECKPOINTERredis depends_on: - redis healthcheck: test: [CMD, curl, -f, http://localhost:8000/healthz] interval: 30s # Agent 层 agent-analyzer: image: yourname/agent-analyzer:1.0 mem_limit: 4g cpus: 1.0 depends_on: - redis healthcheck: test: [CMD, curl, -f, http://localhost:8000/healthz] interval: 20s agent-drafter: image: yourname/agent-drafter:1.0 mem_limit: 6g # 文案 Agent 更吃内存 cpus: 1.5 depends_on: - redis agent-legal: image: yourname/agent-legal:1.0 mem_limit: 8g # 法务 Agent 需加载法律知识库 cpus: 2.0 # 状态层 redis: image: redis:7-alpine command: redis-server --save 60 1 --appendonly yes ports: - 6379:6379 volumes: - ./redis-data:/data # 可观测层 prometheus: image: prom/prometheus:latest volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - 9090:9090 grafana: image: grafana/grafana:latest environment: - GF_SECURITY_ADMIN_PASSWORDadmin ports: - 3000:3000 volumes: - ./grafana-provisioning:/etc/grafana/provisioning # 日志层 loki: image: grafana/loki:latest ports: - 3100:3100 promtail: image: grafana/promtail:latest volumes: - /var/log:/var/log - ./promtail-config.yaml:/etc/promtail/config.yml启动命令# 后台启动所有服务 docker compose up -d # 查看启动状态 docker compose ps # 实时查看调度器日志最关键的日志 docker compose logs -f langgraph-server启动顺序陷阱Docker Compose 默认并行启动所有服务但langgraph-server依赖redis就绪。虽然depends_on声明了依赖但它只保证容器启动顺序不保证redis服务真正可用Redis 启动需 2-3 秒。因此langgraph-server的健康检查interval: 30s至关重要——它会让调度器在 Redis 就绪后再开始接受流量。4.5 步骤 5发起首个端到端测试用curl模拟真实请求验证全链路# 准备测试数据 cat contract.json EOF { input: { contract_text: 甲方应于2024年12月31日前支付全部货款。如逾期乙方有权解除合同并要求甲方支付合同总额20%的违约金。 } } EOF # 发送任务到调度器 curl -X POST http://localhost:8000/invoke \ -H Content-Type: application/json \ -d contract.json \ -o response.json # 查看响应 cat response.json # 应返回包含 analysis_result, draft_versions, legal_feedback 的完整 JSON预期成功响应结构{ status: success, output: { analysis_result: { risk_level: high, suggestions: [建议增加赔偿上限条款, 明确违约金计算方式] }, draft_versions: [ 尊敬的客户根据合同第5条您需在2024年12月31日前支付货款..., 致合作方关于付款期限及违约责任我方建议如下调整..., 合同履行提醒贵司付款义务将于2024年12月31日到期... ], legal_feedback: 第二版草稿中建议如下调整表述模糊需明确具体条款编号。, final_status: pending_revision } }如果失败按以下顺序排查docker compose logs langgraph-server—— 看调度器是否收到请求docker compose logs agent-analyzer—— 看分析 Agent 是否被调用docker exec -it redis-container-id redis-cli ping—— 确认 Redis 连通性4.6 步骤 6配置 CI/CD 自动化部署手动docker compose up只适用于开发。生产环境必须自动化。我们用 GitHub Actions 实现一键部署# .github/workflows/deploy.yml name: Deploy Agent Teams on: push: branches: [main] paths: - agent-analyzer/** - langgraph-server/** jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 # 登录 Docker Hub - name: Login to Docker