Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
<https://functionai.console.aliyun.com/cn-hangzhou/agent/>

## Quickstart

### Step 1 — Configure credentials
Expand Down Expand Up @@ -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).
31 changes: 31 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 控制台:<https://functionai.console.aliyun.com/cn-hangzhou/agent/>

## 快速开始

### 第 1 步 —— 配置凭证
Expand Down Expand Up @@ -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)。
29 changes: 29 additions & 0 deletions docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ option tables and examples.
## Contents

- [Installation](#installation)
- [Prerequisites](#prerequisites)
- [Authentication](#authentication)
- [Global options](#global-options)
- [Output formats](#output-formats)
Expand Down Expand Up @@ -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:
<https://functionai.console.aliyun.com/cn-hangzhou/agent/>

## Authentication

The CLI resolves credentials from three sources, in this order:
Expand Down
6 changes: 6 additions & 0 deletions docs/en/super-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note says missing prerequisites surfaces as exit code 3 (AccessDenied), but the code now also treats other permission/role messages (e.g. NoPermission, EntityNotExist.Role) as exit code 3. Consider rewording to avoid implying the stderr message is always AccessDenied (e.g. “exit code 3 (authentication/permission error)”).

Suggested change
> surfaces as exit code `3` (`AccessDenied`).
> surfaces as exit code `3` (authentication/permission error).

Copilot uses AI. Check for mistakes.

## Commands

Quickstart & chat:
Expand Down
26 changes: 26 additions & 0 deletions docs/zh/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
## 目录

- [安装](#安装)
- [前置准备](#前置准备)
- [认证](#认证)
- [全局选项](#全局选项)
- [输出格式](#输出格式)
Expand Down Expand Up @@ -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 控制台:
<https://functionai.console.aliyun.com/cn-hangzhou/agent/>

## 认证

CLI 按以下顺序解析凭证(上面优先):
Expand Down
6 changes: 6 additions & 0 deletions docs/zh/super-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
该命令组还提供短别名 `ar sa`。会话子组既可用 `ar sa conv` 也可用
`ar sa conversation`,行为一致。

> **使用前提:** 执行本页任何命令前,请先完成
> [前置准备](./index.md#前置准备) 中的两项一次性配置 ——
> 授权 `AliyunAgentRunSuperAgentRole` 角色,并给 AccessKey 挂载
> `AliyunAgentRunFullAccess` 系统策略。任一项缺失都会以退出码 `3`
> (`AccessDenied`)失败。
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里写“退出码 3AccessDenied)失败”,但代码现在也会把 NoPermission / EntityNotExist.Role 等权限/角色相关报错归类为退出码 3。建议改成不强绑定 AccessDenied 文案(例如“退出码 3(权限/认证错误)”)。

Suggested change
> `AccessDenied`)失败。
> 权限/认证错误)失败。

Copilot uses AI. Check for mistakes.

## 子命令

一键拉起与对话:
Expand Down
21 changes: 19 additions & 2 deletions src/agentrun_cli/_utils/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand All @@ -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)
Comment on lines +72 to 74
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prerequisites hint is currently emitted for all _AUTH_PATTERNS, including InvalidAccessKey and SignatureDoesNotMatch. Those cases are not addressed by authorizing the RAM role / attaching AliyunAgentRunFullAccess, so the hint can be misleading. Consider splitting patterns into (a) auth classification patterns and (b) permission/role prerequisite patterns, and only attach PREREQUISITES_HINT for the latter while still exiting with EXIT_AUTH_ERROR for the former.

Copilot uses AI. Check for mistakes.

# Generic fallback
Expand Down
16 changes: 10 additions & 6 deletions src/agentrun_cli/_utils/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

echo_error only includes the hint field when hint is truthy. The docstring says the field is included when hint is provided, so passing an empty string (or other falsy but intentional value) would silently drop the field. Consider checking hint is not None instead of truthiness so the behavior matches the API contract.

Suggested change
if hint:
if hint is not None:

Copilot uses AI. Check for mistakes.
payload["hint"] = hint
click.echo(json.dumps(payload, ensure_ascii=False), err=True)
19 changes: 19 additions & 0 deletions tests/unit/test_error.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Tests for agentrun_cli._utils.error — the handle_errors decorator."""

import json
import sys
from unittest.mock import patch

Expand All @@ -11,6 +12,7 @@
EXIT_BAD_INPUT,
EXIT_NOT_FOUND,
EXIT_SERVER_ERROR,
PREREQUISITES_HINT,
handle_errors,
)

Expand Down Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Loading