diff --git a/AGENTS.md b/AGENTS.md
index 061bf6d..144eb58 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -99,3 +99,7 @@ docs/
- **Cross-link integrity.** When adding a new page or renaming an anchor, update the references in `docs/{en,zh}/index.md`, the two READMEs, and any sibling pages. Anchors use GitHub-slug form (`## Sub-group` → `#sub-group`; Chinese headings preserve the Unicode characters, e.g. `## file 子命令组` → `#file-子命令组`).
- **Source of truth = the code.** Never document options that do not exist in the Click definitions. When the design doc (`docs_inner/cli-design-*.md`) and the code disagree, the code wins — update the user-facing docs to match the code, and flag the divergence in your PR description.
- **No partial updates.** A PR that modifies a command without updating both language versions of the user-facing docs is incomplete; reviewers should block it.
+
+## Commit Requirements
+
+- **Sign off every commit.** All commits in this repository must carry a DCO `Signed-off-by:` trailer. Use `git commit -s` (or pass `-s` alongside `-m`); never push a commit without it. CI / merge gates reject unsigned-off commits, so amending or re-creating commits to add the trailer after the fact is wasted work.
diff --git a/README.md b/README.md
index d42fa13..52c779e 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,33 @@ make build # standalone binary → dist/agentrun
ar --version # or: agentrun --version
```
+## Prerequisites
+
+Two one-time setup steps are required before `ar super-agent` will work:
+
+### 1. Authorize the AliyunAgentRunSuperAgentRole
+
+AgentRun uses a custom RAM service role — **`AliyunAgentRunSuperAgentRole`** —
+to manage runtime resources on your behalf. Open the link below and confirm
+in the RAM console:
+
+[**→ Create AliyunAgentRunSuperAgentRole**](https://ram.console.aliyun.com/authorize?hideTopbar=true&hideSidebar=true&request=%7B%22template%22%3A%22AgentRun%22%2C%22payloads%22%3A%5B%7B%22missionId%22%3A%22SuperAgentCustomRole%22%7D%5D%7D)
+
+Without this role, `ar super-agent run` / `apply` will fail at creation time.
+
+### 2. Grant `AliyunAgentRunFullAccess` to your AccessKey
+
+The AccessKey you save with `ar config set access_key_id ...` must belong to a
+RAM user (or role) that has the **`AliyunAgentRunFullAccess`** system policy
+attached. If you see exit code `3` or `AccessDenied`, this is almost always
+the cause.
+
+### Want more than QuickStart? Use the console
+
+This CLI covers the QuickStart conversational flow end-to-end. For the full
+AgentRun experience, head to the Function Compute AgentRun console:
+
+
## Quickstart
### Step 1 — Configure credentials
@@ -168,6 +195,14 @@ Multi-document YAMLs (`---` separated) let you deploy many agents in one call.
Each page walks through installation, authentication, global options, output formats,
exit codes and every command option with runnable examples.
+## Community
+
+Questions, bug reports and feature requests are welcome on
+[GitHub Issues](https://github.com/Serverless-Devs/agentrun-cli/issues).
+
+For real-time discussion, join the **函数计算 AgentRun 客户群** on DingTalk —
+group number **`134570017218`**.
+
## License
Apache-2.0 — see [LICENSE](./LICENSE).
diff --git a/README_zh.md b/README_zh.md
index c7204b5..d70b48f 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -69,6 +69,30 @@ make build # 本地打独立二进制 → dist/agentrun
ar --version # 或者 agentrun --version
```
+## 前置准备
+
+使用 `ar super-agent` 相关命令前,需要完成两项**一次性**配置:
+
+### 1. 授权 AliyunAgentRunSuperAgentRole
+
+AgentRun 通过自定义 RAM 服务角色 **`AliyunAgentRunSuperAgentRole`** 代你管理
+运行时资源。点击下方链接,在 RAM 控制台完成授权:
+
+[**→ 创建 AliyunAgentRunSuperAgentRole**](https://ram.console.aliyun.com/authorize?hideTopbar=true&hideSidebar=true&request=%7B%22template%22%3A%22AgentRun%22%2C%22payloads%22%3A%5B%7B%22missionId%22%3A%22SuperAgentCustomRole%22%7D%5D%7D)
+
+未授权时 `ar super-agent run` / `apply` 在创建阶段会直接失败。
+
+### 2. 给 AccessKey 授予 `AliyunAgentRunFullAccess`
+
+`ar config set access_key_id ...` 配置的 AccessKey 所属 RAM 用户/角色需要挂载
+系统策略 **`AliyunAgentRunFullAccess`**。命令报 `AccessDenied` 或退出码 `3`
+时,多半就是少了这个权限。
+
+### 想体验更完整的能力?请前往控制台
+
+本 CLI 完整覆盖 QuickStart 快速对话流程。如需体验 AgentRun 的完整能力,请前往
+函数计算 AgentRun 控制台:
+
## 快速开始
### 第 1 步 —— 配置凭证
@@ -166,6 +190,13 @@ ar sa invoke my-helper -m "帮我规划今天的事情" --text-only
每份文档涵盖安装、认证、全局选项、输出格式、退出码以及每个命令的全部选项,附可运行示例。
+## 社区
+
+问题反馈、Bug 报告与功能建议,请走
+[GitHub Issues](https://github.com/Serverless-Devs/agentrun-cli/issues)。
+
+实时交流可加入**函数计算 AgentRun 客户群**,钉钉群号 **`134570017218`**。
+
## License
Apache-2.0 — 详见 [LICENSE](./LICENSE)。
diff --git a/docs/en/index.md b/docs/en/index.md
index 5eab1b1..f447eeb 100644
--- a/docs/en/index.md
+++ b/docs/en/index.md
@@ -10,6 +10,7 @@ option tables and examples.
## Contents
- [Installation](#installation)
+- [Prerequisites](#prerequisites)
- [Authentication](#authentication)
- [Global options](#global-options)
- [Output formats](#output-formats)
@@ -69,6 +70,34 @@ make build # local binary → dist/agentrun
After installation, both `ar` and `agentrun` are available as entry points and behave
identically. `ar` is shorter; the examples in this manual use it.
+## Prerequisites
+
+Two one-time setup steps are required before `ar super-agent` will work.
+
+### 1. Authorize the AliyunAgentRunSuperAgentRole
+
+AgentRun uses a custom RAM service role — **`AliyunAgentRunSuperAgentRole`** —
+to manage runtime resources on your behalf. Open the link below and confirm
+in the RAM console:
+
+[**→ Create AliyunAgentRunSuperAgentRole**](https://ram.console.aliyun.com/authorize?hideTopbar=true&hideSidebar=true&request=%7B%22template%22%3A%22AgentRun%22%2C%22payloads%22%3A%5B%7B%22missionId%22%3A%22SuperAgentCustomRole%22%7D%5D%7D)
+
+Without this role, `ar super-agent run` / `apply` will fail at creation time.
+
+### 2. Grant `AliyunAgentRunFullAccess` to your AccessKey
+
+The AccessKey configured below (see [Authentication](#authentication)) must
+belong to a RAM user (or role) that has the **`AliyunAgentRunFullAccess`**
+system policy attached. If a command exits with code `3` or returns
+`AccessDenied`, this is almost always the cause.
+
+### Want more than QuickStart? Use the console
+
+This CLI covers the QuickStart conversational flow end-to-end. For the full
+AgentRun experience (visual designer, observability, knowledge bases, agent
+marketplace, …), head to the Function Compute AgentRun console:
+
+
## Authentication
The CLI resolves credentials from three sources, in this order:
diff --git a/docs/en/super-agent.md b/docs/en/super-agent.md
index 1294eba..cbce8aa 100644
--- a/docs/en/super-agent.md
+++ b/docs/en/super-agent.md
@@ -9,6 +9,12 @@ You declare intent; the platform hosts the runtime.
Also available as the alias `ar sa`. The conversation sub-group can be reached
as `ar sa conv` or `ar sa conversation`.
+> **Heads up:** before running any command on this page, complete the two
+> one-time setup steps in [Prerequisites](./index.md#prerequisites) — the
+> `AliyunAgentRunSuperAgentRole` authorization and the
+> `AliyunAgentRunFullAccess` policy on your AccessKey. Missing either one
+> surfaces as exit code `3` (`AccessDenied`).
+
## Commands
Quickstart & chat:
diff --git a/docs/zh/index.md b/docs/zh/index.md
index 0d381c4..9aec785 100644
--- a/docs/zh/index.md
+++ b/docs/zh/index.md
@@ -9,6 +9,7 @@
## 目录
- [安装](#安装)
+- [前置准备](#前置准备)
- [认证](#认证)
- [全局选项](#全局选项)
- [输出格式](#输出格式)
@@ -68,6 +69,31 @@ make build # 本地打独立二进制 → dist/agentrun
安装完成后 `ar` 和 `agentrun` 都是入口点,行为完全一致。`ar` 更短,文档里的示例
默认用 `ar`。
+## 前置准备
+
+使用 `ar super-agent` 相关命令前,需要完成两项**一次性**配置。
+
+### 1. 授权 AliyunAgentRunSuperAgentRole
+
+AgentRun 通过自定义 RAM 服务角色 **`AliyunAgentRunSuperAgentRole`** 代你管理
+运行时资源。点击下方链接,在 RAM 控制台完成授权:
+
+[**→ 创建 AliyunAgentRunSuperAgentRole**](https://ram.console.aliyun.com/authorize?hideTopbar=true&hideSidebar=true&request=%7B%22template%22%3A%22AgentRun%22%2C%22payloads%22%3A%5B%7B%22missionId%22%3A%22SuperAgentCustomRole%22%7D%5D%7D)
+
+未授权时 `ar super-agent run` / `apply` 在创建阶段会直接失败。
+
+### 2. 给 AccessKey 授予 `AliyunAgentRunFullAccess`
+
+下文 [认证](#认证) 章节中配置的 AccessKey,所属 RAM 用户/角色需要挂载系统策略
+**`AliyunAgentRunFullAccess`**。命令报 `AccessDenied` 或退出码 `3` 时,多半就是
+少了这一项权限。
+
+### 想体验更完整的能力?请前往控制台
+
+本 CLI 完整覆盖 QuickStart 快速对话流程。如需可视化编排、Observability、
+知识库、Agent 市场等更完整的能力,请前往函数计算 AgentRun 控制台:
+
+
## 认证
CLI 按以下顺序解析凭证(上面优先):
diff --git a/docs/zh/super-agent.md b/docs/zh/super-agent.md
index 8e37c39..22ee04f 100644
--- a/docs/zh/super-agent.md
+++ b/docs/zh/super-agent.md
@@ -9,6 +9,12 @@
该命令组还提供短别名 `ar sa`。会话子组既可用 `ar sa conv` 也可用
`ar sa conversation`,行为一致。
+> **使用前提:** 执行本页任何命令前,请先完成
+> [前置准备](./index.md#前置准备) 中的两项一次性配置 ——
+> 授权 `AliyunAgentRunSuperAgentRole` 角色,并给 AccessKey 挂载
+> `AliyunAgentRunFullAccess` 系统策略。任一项缺失都会以退出码 `3`
+> (`AccessDenied`)失败。
+
## 子命令
一键拉起与对话:
diff --git a/src/agentrun_cli/_utils/error.py b/src/agentrun_cli/_utils/error.py
index 3483e08..782f2cd 100644
--- a/src/agentrun_cli/_utils/error.py
+++ b/src/agentrun_cli/_utils/error.py
@@ -27,6 +27,23 @@
EXIT_AUTH_ERROR = 3
EXIT_SERVER_ERROR = 4
+PREREQUISITES_HINT = (
+ "Complete the one-time setup at "
+ "https://github.com/Serverless-Devs/agentrun-cli#prerequisites — "
+ "authorize the AliyunAgentRunSuperAgentRole and grant "
+ "AliyunAgentRunFullAccess to your AccessKey."
+)
+
+_AUTH_PATTERNS = (
+ "Forbidden",
+ "InvalidAccessKey",
+ "SignatureDoesNotMatch",
+ "AccessDenied",
+ "NoPermission",
+ "AliyunAgentRunSuperAgentRole",
+ "EntityNotExist.Role",
+)
+
def handle_errors(func: Callable) -> Callable:
"""Decorator that catches common SDK / HTTP errors and exits cleanly."""
@@ -52,8 +69,8 @@ def wrapper(*args, **kwargs):
if "ResourceAlreadyExistError" in exc_type or "AlreadyExist" in exc_type:
echo_error("ResourceAlreadyExists", msg)
sys.exit(EXIT_BAD_INPUT)
- if "Forbidden" in msg or "InvalidAccessKey" in msg or "SignatureDoesNotMatch" in msg:
- echo_error("AuthenticationFailed", msg)
+ if any(pattern in msg for pattern in _AUTH_PATTERNS):
+ echo_error("AuthenticationFailed", msg, hint=PREREQUISITES_HINT)
sys.exit(EXIT_AUTH_ERROR)
# Generic fallback
diff --git a/src/agentrun_cli/_utils/output.py b/src/agentrun_cli/_utils/output.py
index c69e851..e2ae87e 100644
--- a/src/agentrun_cli/_utils/output.py
+++ b/src/agentrun_cli/_utils/output.py
@@ -92,9 +92,13 @@ def format_output(ctx: click.Context, data: Any, quiet_field: Optional[str] = No
echo_json(data)
-def echo_error(error_type: str, message: str) -> None:
- """Write a structured JSON error to stderr."""
- click.echo(
- json.dumps({"error": error_type, "message": message}, ensure_ascii=False),
- err=True,
- )
+def echo_error(error_type: str, message: str, hint: Optional[str] = None) -> None:
+ """Write a structured JSON error to stderr.
+
+ When *hint* is provided it is included as a ``hint`` field in the JSON
+ payload — used to surface Prerequisites links on permission failures.
+ """
+ payload: dict = {"error": error_type, "message": message}
+ if hint:
+ payload["hint"] = hint
+ click.echo(json.dumps(payload, ensure_ascii=False), err=True)
diff --git a/tests/unit/test_error.py b/tests/unit/test_error.py
index 5c11c3b..99c7e95 100644
--- a/tests/unit/test_error.py
+++ b/tests/unit/test_error.py
@@ -1,5 +1,6 @@
"""Tests for agentrun_cli._utils.error — the handle_errors decorator."""
+import json
import sys
from unittest.mock import patch
@@ -11,6 +12,7 @@
EXIT_BAD_INPUT,
EXIT_NOT_FOUND,
EXIT_SERVER_ERROR,
+ PREREQUISITES_HINT,
handle_errors,
)
@@ -82,6 +84,23 @@ def test_signature_mismatch_auth_error(self):
_make_raising_func(exc)()
assert exc_info.value.code == EXIT_AUTH_ERROR
+ @pytest.mark.parametrize(
+ "message",
+ [
+ "AccessDenied: user has no permission",
+ "NoPermission to call CreateSuperAgent",
+ "Role AliyunAgentRunSuperAgentRole not authorized",
+ "EntityNotExist.Role: role not found",
+ ],
+ )
+ def test_prerequisite_patterns_emit_hint(self, message, capsys):
+ with pytest.raises(SystemExit) as exc_info:
+ _make_raising_func(Exception(message))()
+ assert exc_info.value.code == EXIT_AUTH_ERROR
+ payload = json.loads(capsys.readouterr().err)
+ assert payload["error"] == "AuthenticationFailed"
+ assert payload["hint"] == PREREQUISITES_HINT
+
def test_generic_exception(self):
exc = Exception("something unexpected")
with pytest.raises(SystemExit) as exc_info:
diff --git a/tests/unit/test_output.py b/tests/unit/test_output.py
index fbc9781..1092796 100644
--- a/tests/unit/test_output.py
+++ b/tests/unit/test_output.py
@@ -155,3 +155,9 @@ def test_writes_to_stderr(self, capsys):
parsed = json.loads(err)
assert parsed["error"] == "TestError"
assert parsed["message"] == "something went wrong"
+ assert "hint" not in parsed
+
+ def test_includes_hint_when_provided(self, capsys):
+ echo_error("AuthError", "denied", hint="see prerequisites")
+ parsed = json.loads(capsys.readouterr().err)
+ assert parsed["hint"] == "see prerequisites"