博客 • AI / Agent

Claude Code 为什么越来越像真正的 AI Agent?从 Tool Use、MCP、Session、Permission 到 JSON Workflow 全面解析

Claude Code 像 Agent,是因为一次会话把三份 JSON 绑在一起:可恢复的对话、每次 Tool Use 都要过的权限,以及启动时读入的 MCP。恢复用 --resume,权限写在 settings.json,工具来自 .mcp.json。缺任何一份,恢复出来的都不是同一次工作。

工具循环本身已经写在 Coding Agent 如何工作。各家 Harness 的差别写在 Harness 大战。本篇只拆 Claude Code:会话恢复什么、权限模式何时变、MCP 何时重新读,以及你该自己留下哪份工作流 JSON。

本文将介绍:

先记住这一点:恢复会话不等于恢复启动参数。对话和部分权限模式会回来,--mcp-config 不会。下面按「会话 → 权限 → MCP → 你的工作流 JSON」拆开。

会话恢复什么,不恢复什么

会话是绑在项目目录上的对话。官方说明见 管理会话。记录持续写到本机,所以退出之后还能回来。

入口 恢复什么 权限模式
claude --continue 当前目录最近一次交互会话的完整对话,含工具调用和结果 终端里不带 -p 时,按官方表恢复;bypassPermissions 和 plan 不会原样回来
claude --resume <name> 按名字直接恢复那一次会话 名字唯一时直接进入;重名则打开选择器,选择器不恢复当时的权限模式
claude -p --resume 非交互恢复,适合脚本 按一次新的 claude -p 来决定模式。会话结束在 plan,且满足官方四个条件时,才回到 plan

恢复时还会带上当时的模型,以及仍有效的目标和未过期的计划任务。后台 Bash 不会回来。

转录默认是 JSONL,路径在 ~/.claude/projects/ 下面、按工作目录转成的文件夹里。官方写明格式会变,不要把它当成你的稳定契约。你要稳定的字段,自己另写一份 JSON。

权限模式跟着会话走

模式不是写在提示词里的。会话中可以用 Shift+Tab 在 default、acceptEdits、plan 之间切。启动时用 --permission-mode,长期默认写在 权限模式 文档里的 permissions.defaultMode。聊天里要求模型换模式,不会改这次会话的闸门。

一次会话的权限默认值和规则。deny 先于 ask,ask 先于 allow。
{
  "permissions": {
    "defaultMode": "default",
    "allow": ["Bash(npm test *)"],
    "ask": ["Bash(git push *)"],
    "deny": ["Read(./.env)", "Read(./.env.*)"]
  }
}

规则顺序见 Claude Code 权限。更具体的 allow 盖不过已经命中的 deny。

怎么恢复 权限模式
终端 --continue 或按唯一名字 --resume,且不带 -p 恢复会话结束时的模式,例外:bypassPermissions 和 plan 会回到新会话该用的模式。auto 只在账号仍满足条件时恢复。
启动时的选择器,或名字对上多个会话 不恢复存下来的模式,按这次启动新会话的模式开始。
/resume 不恢复目标会话存的模式,沿用你当前这次会话的模式。

规则怎么落到审批队列和拒绝回写,见 权限控制怎么接。本篇只说明模式是会话状态,规则文件在恢复时重读。

MCP 在会话启动时读入

项目级服务器写在仓库根的 .mcp.json,会话启动时读取。改完文件要退出再开一次会话。说明见 连接 MCP。第一次看到项目级服务器会要求批准,克隆下来的仓库不能未经同意就在你机器上起进程。

项目级 MCP。服务器名会变成工具名前缀。
{
  "mcpServers": {
    "docs": {
      "type": "http",
      "url": "https://code.claude.com/docs/mcp"
    }
  }
}

工具全名以 mcp__docs__ 这类前缀出现。权限规则按这个全名匹配,不要只写服务器里的短名。

你自己的工作流 JSON

转录 JSONL 不稳定。下面这份是你的应用契约,用来记住下次恢复该传什么。它不是 Claude Code 的请求体,也不会被 CLI 自动读取。

一次可恢复的工作流记录。resume 数组是你下次要补上的参数。
{
  "name": "auth-refactor",
  "cwd": "/repo/app",
  "permission_mode": "default",
  "settings": ".claude/settings.json",
  "mcp_config": ".mcp.json",
  "resume": ["--resume", "auth-refactor"],
  "last_tool": {
    "name": "mcp__docs__search",
    "decision": "allow"
  }
}

name 用 claude -n 或 /rename 设过的名字,方便 --resume 按名字找。cwd 必须是当时的项目目录,会话存在按目录划分的存储里。

  1. 1
    先对上会话

    name 用来 --resume,cwd 用来决定去哪个项目目录找转录。目录不对,同名会话也找不到。

  2. 2
    再对齐权限模式

    把 permission_mode 抄进恢复命令的 --permission-mode。选择器和 /resume 不会帮你恢复旧模式。

  3. 3
    最后补上 MCP

    mcp_config 指向仓库里的文件时,启动会重读。若当时靠的是命令行文件,把路径放进 --mcp-config。

一轮 Tool Use 怎么改这三份文档

一轮不是再写一段提示词。顺序是固定的。

  1. 1
    读入

    会话载入已有对话,并重读 settings.json 与 .mcp.json。命令行 MCP 只有你这次传了才在。

  2. 2
    提出调用

    模型给出 tool_use:工具全名和 input。MCP 工具带服务器前缀。

  3. 3
    过权限

    按 deny、ask、allow 判定。deny 不执行。ask 停下来等人。allow 才调用工具。

  4. 4
    写回

    结果追加进会话转录。你的工作流 JSON 只更新 last_tool,不要把整段转录复制进去。

这样下次恢复时,你知道上次停在哪个工具、当时的模式,以及 MCP 配置从哪个文件读。转录本身仍由 Claude Code 保存。

和另外两篇怎么分工

Coding Agent 如何工作 Harness 大战 本篇
回答的问题 工具循环一般怎么转 各家外壳差在哪 Claude Code 一次会话恢复时,三份 JSON 各管什么
不要在这里找 又一篇工具调用综述 又一张产品对比表 把 JSONL 转录当成稳定 API 来解析

在 JSONNote 里检查工作流 JSON

  1. 1
    格式化

    用 JSON 格式化 打开 settings.json 和工作流记录。注释和尾逗号会让 Claude Code 在下次启动报 Settings Error。

  2. 2
    校验工作流记录

    把下面的 Schema 贴进 JSON Schema。缺 name、cwd 或 permission_mode 不在枚举里,都先改再拿去恢复。

  3. 3
    对比权限规则

    改 deny / allow 前后用 JSON Diff 看一条 deny 有没有被挪进 allow。这种变化比会话名字更值得人看。

工作流记录的 JSON Schema。permission_mode 用官方模式名。
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": ["name", "cwd", "permission_mode", "settings", "mcp_config"],
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "cwd": { "type": "string", "minLength": 1 },
    "permission_mode": {
      "enum": ["default", "acceptEdits", "plan", "auto", "dontAsk", "bypassPermissions"]
    },
    "settings": { "type": "string", "minLength": 1 },
    "mcp_config": { "type": "string", "minLength": 1 },
    "resume": { "type": "array", "items": { "type": "string" } },
    "last_tool": {
      "type": "object",
      "required": ["name", "decision"],
      "properties": {
        "name": { "type": "string" },
        "decision": { "enum": ["allow", "deny", "ask"] }
      }
    }
  }
}

常见问题

resume 之后 MCP 服务器还在吗?

写在 .mcp.json 或 ~/.claude.json 里的会在启动时重读。只通过 --mcp-config 传入的不会自动回来,恢复时要再传。

权限模式会不会和对话一起恢复?

不一定。终端里不带 -p 的 --continue 或唯一名字的 --resume,会按官方表恢复,但 bypassPermissions 和 plan 不会原样回来。选择器和 /resume 用的是当前这次启动的模式。

能不能解析 ~/.claude/projects 里的 JSONL 来做工作流?

不要。官方把转录格式当成会变的内部文件。你要稳定的字段,另写本篇这份工作流 JSON,只记名字、目录、模式、配置路径和上一笔工具决定。

在对话里让模型切换权限模式有用吗?

没用。模式由 Shift+Tab、--permission-mode 或 settings 里的 defaultMode 决定,不由提示词决定。

这和审批队列是同一件事吗?

不是。本篇的 permission_mode 是这一次会话的闸门。队列、拒绝回写和 tool_use_id 见权限控制那篇。两边都要有:模式决定会不会问你,队列决定问了之后怎么落盘。

总结

Claude Code 像 Agent,是因为会话把对话、权限模式和 MCP 工具绑成一次可恢复的工作。恢复对话不等于恢复启动参数。转录 JSONL 留给 CLI,你自己留一份工作流 JSON。

直接结论:用名字和目录定位会话;权限模式在选择器和 /resume 里要显式再传;--mcp-config 每次恢复都要再带上。

下一步:先校验工作流记录,再按里面的 resume 参数打开会话。

返回博客