# 更新动作 (/docs/api/native/automation/updateAction)





检查当前和最近五个历史修订的兼容性后更新。输入放宽、输出收紧为兼容，包括长度、条目数、属性数、type（integer/number）与 multipleOf（输入新因子可整除旧因子，输出相反）。dry_run=true 仅返回 CompatResult，可不带 If-Match；带了仍校验，* 匹配任何当前存在的表示。正常更新必须带 If-Match，返回 ActionDef 与 ETag；预检不返回 ETag。省略的可选字段保持原值仅适用于 description、labels；errors 默认 []，annotations 未提供的键默认 false，timeout_ms 默认 30000，message 默认 null。 正常更新不兼容时返回 422 SCHEMA_INCOMPATIBLE 与 issues；内容未变则保留现有修订。

`PUT /automation/v1/actions/{ns}/{name}`

## 鉴权 [#鉴权]

`Authorization: Bearer $PRAXIS_API_KEY`

## 请求字段 [#请求字段]

| 参数 | 类型 | 说明 |
| --- | --- | --- |
| path: ns | `string` | 必填；命名空间，存储前转为小写，格式 [a-z0-9][a-z0-9._-]&#123;0,63&#125;；praxis 只读。 |
| path: name | `string` | 必填；名称，存储前转为小写，格式 [a-z0-9][a-z0-9._-]&#123;0,63&#125;。 |
| query: dry_run | `boolean` | 可选；true 仅检查兼容性，不落库，可省略 If-Match；省略或 false 正常更新。 |
| header: If-Match | `string` | 可选；正常更新必填；dry_run=true 可省略，提供时仍校验。* 匹配任何当前存在的表示；也可提供当前修订 ETag。 |

### application/json [#applicationjson]

不接受额外字段。

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| description | `string` | 可选；说明，最多 1000 个字符。 maxLength: 1000 |
| labels | `object` | 可选；最多 50 个标签；键为 1–40 个字符，值最多 500 个字符。 |
| input_schema | `object` | 必填 / 必有；输入 JSON Schema；更新时只能放宽已接受的输入。 |
| input_schema.*（分支5).* | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| input_schema.*（分支6)[] | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| output_schema | `object` | 必填 / 必有；输出 JSON Schema；更新时只能收紧输出约束。 |
| output_schema.*（分支5).* | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| output_schema.*（分支6)[] | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| errors | `object[]` | 可选；声明的错误类型与说明；更新时不能删除已有错误。 |
| errors[].type | `string` | 必填 / 必有；错误类型：稳定的 URI，或 Open Workflow 标准类型（如 validation、timeout、communication、runtime）。 |
| errors[].code | `string` | 可选；可选的稳定错误码，供调用方按码分支处理。 |
| errors[].description | `string` | 必填 / 必有；该错误的含义与触发条件，面向调用方阅读。 |
| annotations | `object` | 可选；read_only 与 idempotent 为布尔值，缺省均为 false。 不接受额外字段。 |
| annotations.read_only | `boolean` | 可选；true 表示动作不修改外部状态，只读取数据。默认 false。 |
| annotations.idempotent | `boolean` | 可选；true 表示同一输入重复调用与调用一次效果相同；此类动作的重试使用同一幂等键（run_id 加步骤路径，不含尝试次数）。默认 false。 |
| timeout_ms | `number` | 可选；正整数毫秒；当前 code 默认且最多 30000，container/shell 暂未开放。 |
| implementation | `object` / `object` / `object` | 必填 / 必有；实现：code 使用 language=ts 与 source；container（image、command）和 shell（script）暂未开放，创建或更新时返回 OPERATION_NOT_SUPPORTED。 |
| implementation（分支1).kind | `"code"` | 必填 / 必有；固定为 code：以源码实现。 |
| implementation（分支1).language | `"ts"` | 必填 / 必有；源码语言，目前只支持 ts（TypeScript）。 |
| implementation（分支1).source | `string` | 必填 / 必有；动作的完整 TypeScript 源码。 |
| implementation（分支2).kind | `"container"` | 必填 / 必有；固定为 container：以容器镜像实现（暂未开放，返回 OPERATION_NOT_SUPPORTED）。 |
| implementation（分支2).image | `string` | 必填 / 必有；容器镜像引用。 |
| implementation（分支2).command | `string[]` | 必填 / 必有；在容器中执行的命令及参数列表。 |
| implementation（分支3).kind | `"shell"` | 必填 / 必有；固定为 shell：以 shell 脚本实现（暂未开放，返回 OPERATION_NOT_SUPPORTED）。 |
| implementation（分支3).script | `string` | 必填 / 必有；要执行的 shell 脚本全文。 |
| message | `string` | 可选；本次修订的说明。 |

## 示例 [#示例]

[SDK 安装与示例环境](/docs/api/native/automation)

先设置以下环境变量，使用你自己的资源：

| 变量 | 来源 |
| --- | --- |
| ACTION_NAME | [创建动作返回的 name](/docs/api/native/automation/createAction) |
| ETAG | [最新 GET 响应头 ETag（保留引号）](/docs/api/native/automation/getAction) |

```bash
: "${ACTION_NAME:?Set ACTION_NAME}"
: "${ETAG:?Set ETAG}"
curl --fail-with-body -X PUT "https://api.deepraxis.ai/automation/v1/actions/docs-samples/${ACTION_NAME}" \
  -H "Authorization: Bearer $PRAXIS_API_KEY" \
  -H "If-Match: ${ETAG}" \
  -H "Content-Type: application/json" \
  --data '{
  "input_schema": {
    "type": "object",
    "properties": {
      "n": {
        "type": "number"
      }
    },
    "required": [
      "n"
    ],
    "additionalProperties": false
  },
  "output_schema": {
    "type": "object",
    "properties": {
      "answer": {
        "type": "number"
      }
    },
    "required": [
      "answer"
    ],
    "additionalProperties": false
  },
  "implementation": {
    "kind": "code",
    "language": "ts",
    "source": "export default async (input: { n: number }) => ({ answer: input.n + 1 });"
  },
  "message": "Sample revision"
}'
```

```typescript
import { createAutomationClient } from '@deepractice-ai/praxis-sdk/automation';

function env(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name}`);
  return value;
}
const automation = createAutomationClient({
  apiKey: env('PRAXIS_API_KEY'),
  baseUrl: 'https://api.deepraxis.ai',
  maxRetries: 0,
  timeoutMs: 90_000,
});
const result = await automation.actions.update({
  "path": {
    "ns": "docs-samples",
    "name": env("ACTION_NAME")
  },
  "headers": {
    "If-Match": env("ETAG")
  },
  "body": {
    "input_schema": {
      "type": "object",
      "properties": {
        "n": {
          "type": "number"
        }
      },
      "required": [
        "n"
      ],
      "additionalProperties": false
    },
    "output_schema": {
      "type": "object",
      "properties": {
        "answer": {
          "type": "number"
        }
      },
      "required": [
        "answer"
      ],
      "additionalProperties": false
    },
    "implementation": {
      "kind": "code",
      "language": "ts",
      "source": "export default async (input: { n: number }) => ({ answer: input.n + 1 });"
    },
    "message": "Sample revision"
  }
});
console.log(result);
```

## 响应 [#响应]

### HTTP 200 [#http-200]

Success

| 响应头 | 类型 | 说明 |
| --- | --- | --- |
| ETag | `string` | Current revision returned only for normal updates; absent for dry_run=true. |

`application/json`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| （分支1).id | `string` | 必填 / 必有；动作 ID，前缀 act_；日常调用使用 namespace 与 name，而不是 id。 |
| （分支1).namespace | `string` | 必填 / 必有；动作命名空间；平台动作为 praxis，裸名引用解析到 praxis。 |
| （分支1).name | `string` | 必填 / 必有；动作名，与 namespace 一起唯一标识动作；小写字母、数字、点、下划线、连字符，最长 64 字符。 |
| （分支1).description | `string` | 必填 / 必有；动作说明，最多 1000 字符。 |
| （分支1).labels | `object` | 必填 / 必有；用户自定义标签：字符串键值对，用于分类与列表过滤（labels[key]=value）；键不能以 praxis. 开头。 |
| （分支1).owner | `string` | 必填 / 必有；动作所属租户，由网关注入；按不透明字符串处理。 |
| （分支1).builtin | `boolean` | 必填 / 必有；true 表示平台内置动作（命名空间 praxis）；用户创建的动作为 false。 |
| （分支1).current_revision | `object` | 必填 / 必有；动作的一个不可变修订：契约、实现和运行参数的快照。每次更新兼容的内容变化都会产生新修订。 不接受额外字段。 |
| （分支1).current_revision.id | `string` | 必填 / 必有；修订 ID，前缀 actr_；仅用于展示与回滚（rollback 的 revision），不能被脚本直接引用。 |
| （分支1).current_revision.digest | `string` | 必填 / 必有；契约与实现的内容摘要；内容相同的更新不会产生新修订。 |
| （分支1).current_revision.input_schema | `object` | 必填 / 必有；任意 JSON 对象（键为字符串，值为任意 JSON 值）。 |
| （分支1).current_revision.input_schema.*（分支5) | `object` | 递归 JSON 值。 |
| （分支1).current_revision.input_schema.*（分支6)[] | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| （分支1).current_revision.output_schema | `object` | 必填 / 必有；任意 JSON 对象（键为字符串，值为任意 JSON 值）。 |
| （分支1).current_revision.output_schema.*（分支5) | `object` | 递归 JSON 值。 |
| （分支1).current_revision.output_schema.*（分支6)[] | `null` / `string` / `number` / `boolean` / `object` / `JSON[]` | 递归 JSON 值。 |
| （分支1).current_revision.errors | `object[]` | 必填 / 必有；动作声明的可能错误列表，每项含 type、code、description。 |
| （分支1).current_revision.errors[].type | `string` | 必填 / 必有；错误类型：稳定的 URI，或 Open Workflow 标准类型（如 validation、timeout、communication、runtime）。 |
| （分支1).current_revision.errors[].code | `string` | 可选；可选的稳定错误码，供调用方按码分支处理。 |
| （分支1).current_revision.errors[].description | `string` | 必填 / 必有；该错误的含义与触发条件，面向调用方阅读。 |
| （分支1).current_revision.annotations | `object` | 必填 / 必有；动作行为声明 &#123;read_only, idempotent&#125;；创建时未给出的键默认为 false。 不接受额外字段。 |
| （分支1).current_revision.annotations.read_only | `boolean` | 必填 / 必有；true 表示动作不修改外部状态，只读取数据。 |
| （分支1).current_revision.annotations.idempotent | `boolean` | 必填 / 必有；true 表示同一输入重复调用与调用一次效果相同；此类动作的重试使用同一幂等键（run_id 加步骤路径，不含尝试次数）。 |
| （分支1).current_revision.timeout_ms | `number` | 必填 / 必有；单次执行的超时毫秒数；创建时未给出，code 实现默认 30000，容器或 shell 实现默认 600000。 |
| （分支1).current_revision.implementation | `object` / `object` / `object` | 必填 / 必有；code 使用 language=ts 与 source。container 和 shell 暂未开放，创建时返回 OPERATION_NOT_SUPPORTED。 |
| （分支1).current_revision.implementation（分支1).kind | `"code"` | 必填 / 必有；固定为 code：以源码实现。 |
| （分支1).current_revision.implementation（分支1).language | `"ts"` | 必填 / 必有；源码语言，目前只支持 ts（TypeScript）。 |
| （分支1).current_revision.implementation（分支1).source | `string` | 必填 / 必有；动作的完整 TypeScript 源码；内置动作为空。 |
| （分支1).current_revision.implementation（分支2).kind | `"container"` | 必填 / 必有；固定为 container：以容器镜像实现（暂未开放）。 |
| （分支1).current_revision.implementation（分支2).image | `string` | 必填 / 必有；容器镜像引用。 |
| （分支1).current_revision.implementation（分支2).command | `string[]` | 必填 / 必有；在容器中执行的命令及参数列表。 |
| （分支1).current_revision.implementation（分支3).kind | `"shell"` | 必填 / 必有；固定为 shell：以 shell 脚本实现（暂未开放）。 |
| （分支1).current_revision.implementation（分支3).script | `string` | 必填 / 必有；要执行的 shell 脚本全文。 |
| （分支1).current_revision.host | `"builtin"` / `"isolate"` / `"sandbox"` | 必填 / 必有；动作运行位置，发布时计算。builtin 为平台内置动作；isolate 为在隔离的 Worker isolate 中运行用户代码；sandbox 为在沙箱中运行（container 与 shell 实现）。 |
| （分支1).current_revision.platform_apis | `string[]` | 必填 / 必有；从代码推导出的平台 API 集合，同时是该动作运行令牌的权限范围（最小权限）。 |
| （分支1).current_revision.created_by | `object` | 必填 / 必有；网关注入的主体 &#123;type, id&#125;，表示谁发起或操作；本服务不解析名字，名字由控制台批量解析。 不接受额外字段。 |
| （分支1).current_revision.created_by.type | `"user"` / `"api_key"` / `"agent"` / `"run"` / `"trigger"` | 必填 / 必有；主体类型。user 为登录用户；api_key 为平台 API Key；agent 为智能体；run 为由运行本身（例如父运行）执行的操作；trigger 为触发器。 |
| （分支1).current_revision.created_by.id | `string` | 必填 / 必有；主体标识，含义随 type 而定：用户 ID、API Key ID、智能体 ID、运行 ID 或触发器 ID；按不透明字符串处理。 |
| （分支1).current_revision.message | `null` / `string` | 必填 / 必有；创建该修订时附带的说明；未提供为 null。 |
| （分支1).current_revision.created_at | `string` | 必填 / 必有；该修订的创建时间（RFC 3339 UTC）。 |
| （分支1).stats_7d | `object` | 必填 / 必有；近七天统计；平台动作按调用方租户隔离，只反映当前调用方的调用，不是平台全局统计。 不接受额外字段。 |
| （分支1).stats_7d.calls | `number` | 必填 / 必有；近七天内对该动作的调用次数，按小时汇总。 |
| （分支1).stats_7d.failures | `number` | 必填 / 必有；近七天内失败的调用次数。 |
| （分支1).stats_7d.p50_ms | `null` / `number` | 必填 / 必有；耗时中位数的近似上界，单位毫秒；正耗时向上归入 2 的幂分桶（9 ms → 16 ms），0 独立一桶；无有效耗时样本时为 null。 |
| （分支1).dependents | `object` | 必填 / 必有；引用该动作的脚本与工作流数量，口径为最新版本加草稿。 不接受额外字段。 |
| （分支1).dependents.scripts | `number` | 必填 / 必有；引用该动作的脚本数量。 |
| （分支1).dependents.workflows | `number` | 必填 / 必有；引用该动作的工作流数量。 |
| （分支1).archived_at | `null` / `string` | 必填 / 必有；归档时间；未归档为 null。归档后名字保留，不能复用。 |
| （分支1).created_at | `string` | 必填 / 必有；创建时间（RFC 3339 UTC）。 |
| （分支1).updated_at | `string` | 必填 / 必有；最近一次更新的时间（RFC 3339 UTC）。 |
| （分支2)（分支1).compatible | `true` | 必填 / 必有；固定为 true：新契约与当前及最近五个历史修订兼容。 |
| （分支2)（分支2).compatible | `false` | 必填 / 必有；固定为 false：新契约至少在一处与历史修订不兼容。 |
| （分支2)（分支2).issues | `object[]` | 必填 / 必有；全部不兼容之处，每项含 pointer 与 reason。 |
| （分支2)（分支2).issues[].pointer | `string` | 必填 / 必有；不兼容位置的 JSON Pointer（RFC 6901），相对于动作的 input_schema 或 output_schema。 |
| （分支2)（分支2).issues[].reason | `string` | 必填 / 必有；该位置为何与历史修订不兼容（输入应放宽、输出应收紧）。 |

### 实测响应 [#实测响应]

HTTP 200

```json
{
  "id": "act_00mv67loz4fe4f27bdf89346c885b3a28b2038c091",
  "owner": "tnt_3a9759864ccb4e00",
  "namespace": "docs-samples",
  "name": "sample-action-1791867412840-b05e8a",
  "description": "",
  "labels": {},
  "builtin": false,
  "archived_at": null,
  "created_at": "2026-10-13T04:57:09.039Z",
  "updated_at": "2026-10-13T04:57:12.709Z",
  "current_revision": {
    "input_schema": {
      "type": "object",
      "properties": {
        "n": {
          "type": "number"
        }
      },
      "required": [
        "n"
      ],
      "additionalProperties": false
    },
    "output_schema": {
      "type": "object",
      "properties": {
        "answer": {
          "type": "number"
        }
      },
      "required": [
        "answer"
      ],
      "additionalProperties": false
    },
    "errors": [],
    "annotations": {
      "read_only": false,
      "idempotent": false
    },
    "timeout_ms": 30000,
    "implementation": {
      "kind": "code",
      "language": "ts",
      "source": "export default async (input: { n: number }) => ({ answer: input.n + 1 });"
    },
    "host": "isolate",
    "platform_apis": [],
    "id": "actr_00mv67lrt1370820a9daaa4fd3882332e4899a4c9e",
    "digest": "e35c209873c60486ca8da455878062cb7ea572a6147ce3ca03e0693b4769fa45",
    "created_by": {
      "type": "api_key",
      "id": "key_3e00b8984967"
    },
    "message": "Sample revision",
    "created_at": "2026-10-13T04:57:12.709Z"
  },
  "stats_7d": {
    "calls": 0,
    "failures": 0,
    "p50_ms": null
  },
  "dependents": {
    "scripts": 0,
    "workflows": 0
  }
}
```

## 错误码 [#错误码]

| HTTP | 错误码与说明 |
| --- | --- |
| 400 | INVALID_PARAMS：请求参数、路径、游标或请求体格式无效。 INPUT_INVALID：输入不满足目标契约或业务校验。 |
| 403 | NAMESPACE_FORBIDDEN：命名空间只读或运行令牌不允许此调用。 |
| 404 | ACTION_NOT_FOUND：动作不存在或当前租户不可见；同名脚本/工作流存在时，hint 指向相应接口。 |
| 409 | TARGET_ARCHIVED：目标已归档，不能用于本操作；动作执行错误的 detail 包含 ns/name。 |
| 412 | PRECONDITION_FAILED：修订、源码摘要或并发写入条件不匹配。 |
| 413 | PAYLOAD_TOO_LARGE：请求内容超过本操作允许的大小。 |
| 422 | SCHEMA_INCOMPATIBLE：新动作契约与历史修订不兼容。 |
| default | RFC 9457 automation problem. 429 includes Retry-After. |

[鉴权错误与通用错误](/docs/api/errors) · 排查时保留响应头 `X-Request-Id`。
