# agent_enbedded **Repository Path**: liaofde/agent_enbedded ## Basic Information - **Project Name**: agent_enbedded - **Description**: agent_enbedded - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-20 - **Last Updated**: 2026-10-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 嵌入式 Agent · 配置与断连恢复优化版 远端目录:`/home/yt/agent_embedded` ## 1. 启动 ```bash cd ~/agent_embedded ./start_agent.sh eth2serial 8000 # 工程名 端口(默认 freertos_apollo / 8000) tail -f agent.log ./stop_agent.sh ``` 前台调试: ```bash source venv/bin/activate python3 run.py --project eth2serial --port 8000 --no-sandbox python3 run.py --project eth2serial --show-config # 只打印最终生效配置 ``` ## 2. 两级配置(重点) ### 2.1 入口文件:人工维护,路径必填 + 可选默认参数 原机制:`--project <名字>` 读取 `projects/<工程名>.json`。该文件由人工创建和维护,程序只读不改写。 ``` /home/yt/agent_embedded/projects/<工程名>.json # 主入口(原机制,人工维护,本机文件不入库) /home/yt/agent_embedded/<工程名>.json # 兼容后备,仅当 projects 下不存在时使用 ``` 仓库里只保留 `projects/example.json` 模板;实际工程入口由使用者本地复制创建, 已在 `.gitignore` 中排除(`projects/*.json`,仅放行 `example.json`)。 `path` 必填;其余字段是可选的**默认参数**,只在 `<工程>/agent_embedded/<工程名>.json` 不存在、需要自动生成时使用。示例: ```json { "path": "/path/to/your/project", "allowed_write_subdirs": ["Core", "User", "build"], "allow_target": ["clean", "flash-fast", "readback"] } ``` 启动时会校验:路径必须存在、是绝对路径、是目录、可读;不合法直接拒绝启动并给出原因。 正常运行只从入口读 `path` 用于定位工程;工程名只来自 `--project` 参数, 任何 `.py` 里都不写死工程名。 ### 2.2 运行配置:工程目录下,缺失自动生成,可热改 ``` <工程路径>/agent_embedded/<工程名>.json 例:/home/yt/eth2serial/agent_embedded/eth2serial.json ``` **检测到该文件不存在时(首次启动、被删除、整个目录被删除)自动生成默认配置**: 入口文件里除 `path` 外的字段 + 内置默认值;服务运行中被删除也会在下一次工具调用时自动重建。 之后所有参数都从这里读取;**保存后下一次工具调用立即生效,不需要重启**(按文件 mtime 检测)。 JSON 写坏/字段非法时保留上一份可用配置并打印告警,不会拖垮正在执行的任务。 注意:删除该文件等于“恢复默认配置”,手工改过的值会按入口默认参数重建。 字段说明: | 字段 | 作用 | | --- | --- | | `allowed_write_subdirs` | 允许写入的顶层目录;空数组=除只读目录外不限制 | | `readonly_subdirs` | 只读顶层目录,优先级高于写白名单 | | `tools_enabled` | 各工具开关;`build_cmd` 为编译命令 | | `allow_target` | **make 目标白名单**,原 `fs_tools.py` 里写死的列表搬到这里 | | `make_timeout_sec` | make 超时,默认 300 秒 | | `build_timeout_sec` | 编译超时,默认 600 秒 | | `max_tree_depth` | 目录树最大深度 | | `max_read_chars` | 单次读取上限,超长文件用 `start_line/max_lines` 分段读 | | `max_tool_output_chars` | 单个工具输出上限,避免 make 日志塞满上下文 | 新增 make 目标(在线生效): ```json "allow_target": [ "jlink-check", "clean", "flash-fast", "flash", "readback", "erase", "verify-run", "verify-uart", "size", "reset" ] ``` 保存后直接让 Agent 执行 `run_make("size")` 即可,不用改 `tools/fs_tools.py`。 Agent 也可以调用 `get_project_config()` 随时查看当前实时生效的 `allow_target`。 > 提示:`start_agent.sh` 默认带 `--no-sandbox`(写目录白名单不生效,仍拦截路径逃逸)。 > 需要严格按 `allowed_write_subdirs` 管控时,去掉 `--no-sandbox` 启动。 ## 3. LLM 断连与会话续跑 ### 3.1 根因 旧版 `ChatOpenAI(timeout=25)` 把连接/读超时都卡在 25 秒;复杂任务上下文大、回答长, 很容易触发 `OpenAITimeoutError`,SDK 重试后仍失败就表现为 `OpenAIConnectionError('Connection error.')`。 同时会话只存在内存里:服务重启/网页刷新后 session_id 变化,历史全部丢失。 ### 3.2 现在的处理 1. **超时拆分**:connect 15s / read 180s / write 30s / pool 30s,可通过 `agent.env` 调整。 2. **流式输出** `LLM_STREAMING=1`:连接上持续有数据帧,避免中间设备按空闲连接回收。 3. **两层重试**:OpenAI SDK 自动重试(`LLM_MAX_RETRIES=4`,指数退避), Agent 层再按断点续跑(`AGENT_RETRY_ATTEMPTS=3`)。 4. **LangGraph 检查点**:会话状态落在 `sessions/checkpoints.sqlite`。 失败后若存在待执行节点,用 `invoke(None)` 从断点继续,已经跑完的工具(读文件、编译)不会重跑。 5. **会话持久化**:网页 session_id 存 `localStorage`;刷新/服务重启后同一会话自动恢复历史。 若上一轮中断,页面提示"上一轮未完成,发送任意消息会自动续跑"。 6. **心跳**:长任务执行中后端每 15 秒发心跳,前端空闲超时改为 10 分钟且随心跳重置。 7. **步数上限**:`AGENT_RECURSION_LIMIT=100`,避免复杂任务 25 步被截断。 8. **上下文保护**:长会话估算超过 `AGENT_HISTORY_MAX_TOKENS` 时,自动裁掉最旧的完整轮次 (保留最近 `AGENT_HISTORY_KEEP_TURNS` 轮),避免历史无限增长撑爆上下文后永久报错。 可在 `agent.env` 覆盖: ```ini LLM_CONNECT_TIMEOUT=15 LLM_READ_TIMEOUT=180 LLM_MAX_RETRIES=4 LLM_STREAMING=1 AGENT_RETRY_ATTEMPTS=3 AGENT_RECURSION_LIMIT=100 AGENT_HEARTBEAT_SEC=15 AGENT_HISTORY_MAX_TOKENS=80000 AGENT_HISTORY_KEEP_TURNS=4 # AGENT_SESSION_DB=/home/yt/agent_embedded/sessions/checkpoints.sqlite ``` ## 4. 观测接口 - `GET /api/health`:服务/工程/检查点路径 - `GET /api/config`:当前生效配置(含 `allow_target`、来源文件、上次热加载错误) - `GET /api/session//history`:会话历史 + `pending`(是否还有断点可续跑) ## 5. 安装 / 修复 venv 新机器直接运行: ```bash ./install.sh # 已有可用 venv 则复用并补装依赖 ./install.sh --recreate # venv 损坏/缺 ensurepip 时删除重建 PYTHON_BIN=python3.10 ./install.sh # 指定解释器 ``` `install.sh` 会自动处理: - 已有 venv 不完整(`bin/python3` 不可用)→ 自动删除重建; - venv 里没有 `pip` → 先尝试 `ensurepip`,失败再用 `get-pip.py` 补装; - `python3 -m venv` 失败(常见于 Ubuntu 未装 `python3-venv`)→ 清理残留后改用 `python3 -m venv --without-pip` + 补 pip,仍失败再尝试 `virtualenv`; - 所有方式都失败 → 打印 apt/yum 修复命令,不会留下半成品 venv; - 最后统一用 `venv/bin/python -m pip` 升级 pip 并安装 `requirements.txt`, 避免 `venv/bin/pip` 缺失导致报错。 新增依赖 `langgraph-checkpoint-sqlite`(SQLite 会话检查点)已包含在 `requirements.txt`。 自测脚本 `tests/` 是本机开发验证用的,依赖具体工程路径、LLM 与板卡环境, 不属于运行必需,**未纳入仓库**(已加入 `.gitignore`)。本机保留时可运行: ```bash ./venv/bin/python tests/test_runtime_config.py # 配置/热加载/白名单/工具 bash tests/integration.sh # 端到端:会话持久化、断连续跑 ``` ## 6. 新建工程 1. 复制模板: ```bash cd ~/agent_embedded cp projects/example.json projects/<工程名>.json ``` 2. 修改 `path` 为工程真实绝对路径(必须存在、可读);按需修改 `allowed_write_subdirs` / `readonly_subdirs` / `allow_target` 等默认参数。 3. 启动: ```bash ./start_agent.sh <工程名> 8000 ``` 4. 首次启动会自动生成 `<工程路径>/agent_embedded/<工程名>.json`; 之后只改这个运行配置,保存即热生效。入口文件 `projects/<工程名>.json` 只读不改写。 工程名只来自 `--project` 参数,不需要改任何 `.py`。