如何在脚本和 CI 中无头运行 Jan Agent(jan cli agent run)?
【免费下载链接】janJan is an open source alternative to ChatGPT that runs 100% offline on your computer.项目地址: https://gitcode.com/GitHub_Trending/ja/jan
Jan Agent 的jan命令不带子命令时会打开交互式控制台,但在脚本或 CI 流水线里,你需要的是不弹界面、跑完即退出的执行方式。这正是jan cli agent run的用途:把一段任务文本作为位置参数传进去,Agent 会一直运行到任务完成或会话 token 预算耗尽,然后用退出码告诉你结果。适用前提是机器上已安装 Jan Agent CLI,并且已配置好至少一个模型 provider——Jan Agent 不自带推理引擎,模型始终运行在 provider 侧(云端、Tokamak 或你自己的 OpenAI 兼容端点)。
准备条件
在 CI 机器或跑脚本的终端上先装好 CLI。macOS / Linux:
curl -fsSL https://delta.jan.ai/jan-cli/install-jan-agent.sh | bashWindows(PowerShell):
irm https://delta.jan.ai/jan-cli/install-jan-agent.ps1 | iex安装脚本默认装到~/.local/bin,可以用环境变量JAN_INSTALL_DIR覆盖安装目录(例如JAN_INSTALL_DIR=/usr/local/bin),并确保该目录在PATH上。验证方式:
jan --version如果报jan: command not found,说明安装目录不在PATH中,把~/.local/bin加进 shell profile 即可。
然后确认 provider 可用。Jan Agent 不带本地推理,必须有一个远程 provider。四种配置来源按优先级从高到低是:单次运行的--provider/--api-key或环境变量JAN_API_KEY/<PROVIDER>_API_KEY(如ANTHROPIC_API_KEY)→ 项目agent.toml中的[provider]→ Jan Desktop 的settings.json(仅继承,不覆盖)→~/.jan/config.toml。CI 场景通常走环境变量或jan config set:
jan config set --provider anthropic --api-key sk-ant-...确认配置是否就绪(API key 会被打码):
jan config list注意jan config list可能显示为空,而jan cli models list列出了模型——这不是 bug,后者还会包含从 Jan Desktop 继承的 provider。
基本运行:jan cli agent run
run子命令以位置参数接收任务文本,跑完即退出。文档给出的示例形态:
jan cli agent run "fix the failing test in tests/auth" jan cli agent run --project ~/code/app "update the changelog" jan cli agent run --model gpt-4o "add unit tests for the parser" jan cli agent run --safe "run the migration" # approve each step与无头运行相关的关键 flag:
| Flag | 说明 |
|---|---|
--project <PATH> | 项目根目录,默认. |
--model <ID> | 模型 id,覆盖[agent].model |
--safe | 写文件、shell 命令和 MCP 工具调用前要求批准 |
--sandbox | shell 命令在 OS 隔离下运行,默认关闭 |
--no-sandbox | 覆盖持久化的sandbox设置,本次不隔离运行 |
--resume[=ID] | 恢复最近一次会话或指定 id 的会话 |
-c,--continue | 恢复最近一次会话 |
--provider,--api-key | 本次运行的凭据覆盖 |
--output-format <FORMAT> | text(默认)流式输出回答;json打印一个结果对象 |
两个必须知道的行为边界:
- 没有轮数上限。Agent 会跑任务需要的所有轮次,唯一的上限是
agent.toml里[budget].max_tokens(未设置时默认128000,设为0表示不限),或者你主动取消。 --resume必须用等号形式。因为run的位置参数会"吃掉"空格分隔的 id,所以要写--resume=3f7a91c2而不是--resume 3f7a91c2。
用 JSON 输出驱动脚本
把--output-format json加上后,流式回答被抑制,运行结束时在 stdout 打印一个对象;进度和诊断信息走 stderr,所以 stdout 可以直接管道给jq:
jan cli agent run --output-format json "review auth.rs" | jq -r .result成功时文档给出的示例输出(示例结果,字段值会随任务变化):
{ "type": "result", "is_error": false, "result": "APPROVED: the retry loop is correct...", "stop_reason": "end_turn", "session_id": "3f7a91c2", "model": "tokamak-1-preview", "num_turns": 3, "duration_ms": 48213, "usage": { "prompt_tokens": 9011, "completion_tokens": 655, "total_tokens": 9666 } }失败时对象会多出error字段,stop_reason变为error,result里是中断前模型已经说出的部分回答,session_id为null:
{ "type": "result", "is_error": true, "result": "I started reviewing auth.rs and...", "stop_reason": "error", "error": { "code": "upstream_error", "message": "[400] tool_choice does not match any of the specified tools" }, "session_id": null, "model": "tokamak-1-preview", "num_turns": 1, "duration_ms": 1204, "usage": { "prompt_tokens": 8123, "completion_tokens": 0, "total_tokens": 8123 } }字段含义(摘自 CLI Reference 的字段表):
| 字段 | 说明 |
|---|---|
result | 最终回答,或失败那一轮的部分回答;推理内容会被剥离 |
stop_reason | 上游 finish reason,或error |
error.code | context_overflow、upstream_error、setup_error或原始错误码 |
session_id | 供--resume用的短会话 id;运行在产出 id 前就失败时为null |
num_turns | 本 Agent 花费的轮数,子 Agent 轮次不计入 |
usage | 整个运行所有请求的累计值,含子 Agent |
退出码不随输出格式变化:成功0,失败1。CI 判断可以直接用退出码,需要结果文本时再解析 JSON。
CI 中的完整示例
文档给出的 CI 模式:凭据从环境来、全程无交互:
export ANTHROPIC_API_KEY="$SECRET_KEY" jan cli agent run \ --project . \ --provider anthropic \ "update the changelog for the current release"这里没有加任何审批 flag 是刻意的:工具调用默认自动批准,这正好是 CI runner 需要的状态,因为没有人坐在键盘前回答提示。千万不要在这种无 TTY 的环境传--safe——stdin 上没有 TTY 时无法回答批准提示,每个提示都会被拒绝,运行会在第一次写操作处卡死。
需要提醒的安全边界:默认自动批准同时意味着 shell 命令不做沙箱隔离,批准过的命令会以你(runner 用户)的权限运行。如果你希望 CI 里命令被限制在项目目录内,加--sandbox(Linux 用 bubblewrap、macOS 用 Seatbelt、Windows 用 AppContainer);隔离生效时命令只能写项目目录及其 scratch 目录,网络访问也受[tools].allow_network控制。注意一个组合行为:enabled: true但机器上没有可用 sandbox backend(jan cli agent status会报告backend)时,bash工具会被整个扣住,命令根本不会执行。
验证运行环境与结果
无头运行前后都可以用非交互命令核对状态:
# 查看解析后的项目配置与可用 provider(也是首次 scaffold .jan/agent/ 的方式) jan cli agent status jan cli agent status --project ~/code/appstatus会打印解析后的项目配置,其中包括 sandbox 实际会怎样运行(文档示例):
"sandbox": { "enabled": false, "backend": "bubblewrap" }运行结束后,会话按项目保存在.jan/agent/threads下,可以从 shell 直接检查(输出是 JSON,可接jq):
jan cli threads list jan cli threads messages <THREAD_ID>如果要在后续脚本步骤里续接上一次无头运行,用等号形式的 resume:
jan cli agent run --resume=3f7a91c2 "carry on"注意会话是按项目存储的,从别的目录 resume 找不到会话属于预期行为,不是 bug。
相关配置与限制
- 预算:
[budget].max_tokens是单次运行唯一的长度上限,统计的是所有轮次新增的 token 花费(重放的上下文不重复计费)。在 CI 里它是防止失控运行的主要手段,设为0可禁用上限。 - 工具策略:
.jan/agent/agent.toml的[tools]段决定默认档位(read-only/deny/allow)、白名单和黑名单。deny永远优先于allow。无论哪种模式,.jan/agent/内部文件、[tools] deny中的条目都是硬性禁止,任何模式都解不开。 - 项目级 provider:某个项目必须用特定 provider 时写在
agent.toml的[provider]段。文档建议不要把它提交到仓库时带着api_key,key 应留在~/.jan/config.toml或环境变量里。 - 项目目录约定:建议把
agent.toml、AGENT.md、skills/、subagents/提交进版本库让团队共享同一套 Agent 配置,threads/是个人会话记录,应加入.gitignore。 - 无 TTY 的硬限制:
--safe在无 TTY 环境下不可用(第一次写入即卡死);这也是文档在 run modes 中单独警告的点。
更多 flag 与子命令(jan cli agent step单轮调试、jan plugin、jan cli mcp等)见 CLI Reference;权限模型细节见 Tool Permissions,预算与agent.toml全字段见 Project Config,provider 优先级见 Providers。
【免费下载链接】janJan is an open source alternative to ChatGPT that runs 100% offline on your computer.项目地址: https://gitcode.com/GitHub_Trending/ja/jan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考