# ArcBlock — full content --- ## AFS URL: https://www.arcblock.io/en/docs/afs/ --- ## Author a provider URL: https://www.arcblock.io/en/docs/afs/author-a-provider/ Start from a provider covered by current tests, not from an old planning document. In the ARC source tree: | Artifact | Role | |---|---| | `providers/core/json/src/index.ts` | Compact implementation baseline (`AFSJSON` extends `AFSBaseProvider`) | | `providers/core/json/test/conformance.test.ts` | Conformance fixture via `runProviderTests` | | `packages/testing` (`@aigne/afs-testing`) | Shared suite runner and contract-gated fixtures | | `docs/guides/provider-authoring.md` | Authoring discipline (ops vs semantic actions, ifMatch, query) | ## Minimal public contract | Piece | What to implement | |---|---| | Module identity | `name`, optional `description`, `uri` / load params | | Path ownership | Stable path layout; no reserved virtual prefix abuse (`.actions`, `.meta`, `.as`, …) | | Operations | Only methods you can enforce: `list` / `read` / `write` / `delete` / `stat` / `search` / `exec` / `explain` / `rename` / optional `query` / optional batch | | Capability declaration | `OperationsDeclaration` (+ features). **Declare ⇒ execute**; never advertise ifMatch/query without enforcement | | Errors | Use shared `AFS*Error` codes (`AFS_NOT_FOUND`, `AFS_VALIDATION_ERROR`, `AFS_CONFLICT`, …) | | Conformance | `test/conformance.test.ts` calling `runProviderTests` | Typical baseline pattern (JSON provider): 1. Extend `AFSBaseProvider`. 2. Provide `static manifest()` / `load()` for registry/URI loading. 3. Decorate handlers with `@List`, `@Read`, `@Write`, `@Delete`, `@Search`, `@Stat`, `@Explain`, … 4. Override `getOperationsDeclaration()` when you need features such as `ifMatch`. 5. Expose `/.meta/.capabilities` for runtime discovery. ## Run the JSON baseline conformance From a current ARC monorepo checkout (package `@aigne/afs-json`): ```bash pnpm --filter @aigne/afs-json test -- test/conformance.test.ts ``` Verified on ARC source `44fbd616f` (2026-08-10): ```text 372 pass 6 skip 0 fail Ran 378 tests across 1 file. ``` Treat that result as evidence for **this baseline and this commit**, not for every provider or every release. Skipped suites (for example subscribe when not declared) are expected when fixtures omit optional capabilities. ## Suggested implementation order 1. Sketch the FS layout (directories vs leaves vs action paths). 2. Implement inspection first: `list` + `read` (+ `stat`/`explain`). Anything stored should be enumerable—do not hide data only behind custom actions. 3. Add path mutation (`write`/`delete`/`rename`) only where the store can enforce it. 4. Add semantic `@Actions` only for operations that need provider-specific meaning beyond path CRUD. 5. Wire `runProviderTests` with a `structure` fixture matching real data. 6. If you declare `query`, ship a `collectionQuery` fixture (declare ⇒ test). 7. If you declare `write.features.ifMatch`, ship `ifMatch` **and** `peerProvider` against the same backing store. 8. Document data, auth, search, and failure boundaries separately from the generic AFS contract. Do not claim `query` because you can `list`, or a particular search quality because you expose `search`. ## Keep an acceptance record Use this record before presenting a provider as a public catalog candidate. It is a checklist, not a claim that every provider has already passed it. | Record | What to capture | |---|---| | Contract | Owned paths, operations, declared capabilities; do not infer one from another | | Data and access boundary | Backing system, credentials or caller boundary, data read/changed, observable failures | | Conformance evidence | Exact test command, ARC/source version, pass/skip/fail counts | | Local acceptance | Isolated local exercise: ARC version, commands, non-secret env choices, observed result. Do **not** substitute DID Space deploy for local evidence | | Compatibility | ARC/runtime version and provider backend versions the observation depends on | | Support ownership | Maintainer, lifecycle state, documentation location users should rely on | If any row is unknown, keep the provider out of the public catalog. A package in the source tree is implementation evidence, not a support promise. See [Provider catalog](../provider-catalog/). --- ## Core contract URL: https://www.arcblock.io/en/docs/afs/core-contract/ AFS exposes path operations. The provider responsible for a path supplies the operation and its behavior. Do not model the API as one universal filesystem with mandatory support for every verb. Evidence for this page: `packages/core/src/type.ts` (`AFSModule`, `AFSRoot`), `packages/core/src/afs.ts`, `packages/core/src/capabilities/types.ts` (`OperationsDeclaration`), `packages/core/src/error.ts`, checked against ARC source `44fbd616f` and CLI `arc` `2.0.0-beta.28`. ## Operation families | Operation | Module method (core) | Purpose | Capability boundary | |---|---|---|---| | `list` | `list?` | Enumerate entries under a path | Options and listing semantics are provider-defined; unsupported list flags may be best-effort | | `read` / batch read | `read?`, optional `batchRead?` | Read one or more resources | Depends on provider and path; `visibility: "meta"` returns meta only | | `write` / batch write | `write?`, optional `batchWrite?` | Create or change content | Writable is not implied by path existence; write modes include replace/append/prepend/patch/create/update | | `delete` / batch delete | `delete?`, optional `batchDelete?` | Remove resources | Recursive and predicate options are provider/feature-specific | | `rename` | `rename?` | Move/rename within provider rules | Not every CLI surface exposes rename; check core/API and provider | | `stat` | `stat?` | Inspect metadata | Shared result envelope; fields inside are provider-defined | | `search` | `search?` | Free-text retrieval | Coverage and ranking are provider-defined; see [Search and query](../search-and-query/) | | `exec` | `exec?` | Invoke an action at a path | Requires explicit action path, args, and permission/severity policy | | `explain` | `explain?` | Report how a path resolves | Use for routing and ownership inspection | | `query` | `query?` (optional) | Typed collection query via `/.actions/query` | Optional and **strict**; declare fully or not at all | Optional methods on `AFSModule` are real: a provider that omits a method does not implement that operation. Root `AFSRoot` requires the common ops at the dispatcher level and still routes through mount capabilities. ## Capability declaration Providers declare operations through `OperationsDeclaration` (boolean or `{ supported, features }`): | Field | Notes | |---|---| | `read`, `list`, `write`, `delete`, `search`, `exec`, `stat`, `explain` | Core op flags | | `query?` | Mirrors the standard collection-query action for tooling | | `batchWrite?`, `batchDelete?` | Often derived; pushdown needs method presence + `features.batchPushdown` | | `subscribe?`, `interact?` | Optional event / human-elicitation capabilities | Sub-capability features (examples): | Feature | Meaning when declared | |---|---| | `write.features.ifMatch` | Optimistic concurrency via opaque `meta.version`; must enforce or reject, not silent degrade | | `list.features.orderBy` | Server-side list ordering | | `delete.features.where` | Predicate delete | Read live declarations when available: ```bash arc afs read /.meta/.capabilities ``` ## Access mode and visibility | Concept | Values | Effect | |---|---|---| | `accessMode` | `readonly` · `create` · `append` · `readwrite` | Constrains which mutations are allowed at the module/mount | | `visibility` | `full` · `meta` | `meta`: read returns metadata only; search denied | Do not assume `readwrite` from the fact that a path lists children. ## Error codes (selected) From `packages/core/src/error.ts`. Applications should branch on `code`, not English message text alone. | Code | Class | Typical cause | |---|---|---| | `AFS_NOT_FOUND` | `AFSNotFoundError` | Path does not exist | | `AFS_UNSUPPORTED` | `AFSUnsupportedError` | Operation not supported | | `AFS_VALIDATION_ERROR` | `AFSValidationError` | Bad args or strict query/spec failure | | `AFS_READONLY` | `AFSReadonlyError` | Mutation against readonly surface | | `AFS_ACCESS_MODE` | `AFSAccessModeError` | Violates mount access mode | | `AFS_ACCESS_DENIED` | `AFSAccessDeniedError` | Substrate access denied | | `AFS_FORBIDDEN` | `AFSForbiddenError` | Policy forbid | | `AFS_AUTH_REQUIRED` | `AFSAuthRequiredError` | Mutating action needs auth | | `AFS_CONFLICT` | `AFSConflictError` | `ifMatch` version mismatch | | `AFS_ALREADY_EXISTS` | `AFSAlreadyExistsError` | Create/collision | | `AFS_MOUNT_FAILED` | `AFSMountError` | Mount check failed | | `AFS_ACTION_NOT_FOUND` | `AFSActionNotFoundError` | Unknown action | CLI observation on beta.28: missing path via `arc afs read` prints `ERROR: Path not found: …` and exits `5`. ## CLI vs core surface | Surface | Ops commonly exposed | |---|---| | `arc afs` (beta.28) | `ls`, `read`, `write`, `delete`, `stat`, `exec`, `explain`, `search`, `mount` | | Core `AFSModule` | Above plus `rename`, optional `query`, optional batch pushdown, `subscribe`, etc. | If you need an operation that is in core types but missing from the CLI group, use the programmatic/RPC surface or check whether a root `/.actions/*` action covers it. See [arc afs](../../arc-cli/command-reference-afs/). ## Provider authors Implement an `AFSModule` (typically via `AFSBaseProvider` and operation decorators), expose only operations you can enforce, and run shared conformance tests. Continue with [Author a provider](../author-a-provider/). --- ## Browse AFS with the Explorer URL: https://www.arcblock.io/en/docs/afs/explorer/ Use this page to browse a **running local AFS surface** in a browser instead of the CLI. Everything below was verified against a local daemon running `arc` `2.0.0-beta.34`, with the AFS Explorer blocklet served at `http://explorer.localhost:4900`. Your mounts, paths, and children will differ. For the CLI equivalent of every read operation here, see [Inspect a local AFS surface](../local-inspection/). The Explorer is declared with `scope: root`: it sees your **entire** AFS namespace, including every mount. Treat it as a private inspection surface for your own machine or your own deployment, and apply the same secret-hygiene rules as [`arc afs mount list`](../local-inspection/) output — provider URIs visible in the tree can embed tokens. ## 1. Open the Explorer On a local daemon (started via `arc`), the Explorer answers on the `explorer.localhost` domain of the daemon port: ```text http://explorer.localhost:4900/ ``` The URL path **is** the AFS path. Navigating to `/registry/providers` in the app puts `/registry/providers` in the address bar, and pasting that URL back opens the same directory. Selecting a file adds a `?sel=` query parameter: ```text http://explorer.localhost:4900/registry/providers ← directory = URL path http://explorer.localhost:4900/modules/project?sel=%2Fmodules%2Fproject%2FREADME.md ``` Both forms are shareable deep links. One verified caveat: on first load the app may restore the location you visited last instead of the URL you pasted — load the URL a second time and it lands correctly (see [Failures to expect](#failures-to-expect)). ## 2. Read the four panes | Pane | What it shows (verified) | |---|---| | **Sidebar** | A directories-only tree of the whole namespace with its own filter box. It auto-expands to the path you are on. Below it, a **Tags** section shows `No tags yet` until entries carry tags. | | **Primary list** | The current directory: view-mode toggle (`☰` list, `▦` grid, `▶` slideshow), a filter box, a clickable breadcrumb, a `..` row, and one row per entry with type and size badges. Long directories load incrementally; a footer such as `69 of 185` shows how much of the directory is loaded. | | **Inspector** | The selected entry: name and size header, **Download / Open / Copy link** actions, collapsible **Details** and **About** sections, and a **Preview**. | | **Status bar** | The static text `Ready`. It is not an activity indicator. | ![AFS Explorer root directory: sidebar tree with mount descriptions, primary list with checkboxes, inspector preview, status bar](media/01-root-overview.png) ## 3. Navigate | Action | Result (verified on beta.34) | |---|---| | Click an entry | Selects it; the inspector updates and `?sel=` is added to the URL | | Double-click a directory | Opens it | | Click `..` or a breadcrumb segment | Goes up / jumps to that ancestor | | `↑` / `↓` | Moves the selection (URL `?sel=` follows) | | `Enter` | Opens the selected directory | | `Backspace` | Goes to the parent directory | | Sidebar directory click | Jumps there; the tree expands along the way | Type in either filter box to narrow the tree or the current listing. ![Breadcrumb and provider catalog at /registry/providers with the sidebar tree expanded to the same path](media/02-registry-providers.png) ## 4. Inspect a file Select a file and open **Details**. Verified fields for a file on a local `fs` mount: ```text path /modules/project/README.md version 177993786…721-5320 ← opaque optimistic-concurrency token kind fs:file access readwrite modified 2 months ago | May 27, 2026, 8:11 PM capabilities list read stat search write delete exec explain ``` The **Preview** renders what it can inline — verified: Markdown files render as formatted text, images load through a signed `/api/afs/raw` URL, and directories show an item list. Entries the preview cannot render inline (verified with a `registry:guide` node) show `No preview available` plus a working **Download** link. **Download / Open / Copy link** are the only actions in the inspector header — the list row additionally offers **Collect** (see section 6). ![Inspector showing Details metadata and a rendered Markdown preview for README.md](media/03-file-inspector-preview.png) ## 5. Switch views - **List `☰`** — rows with mime-type and size badges, selection checkboxes, and per-row actions. - **Grid `▦`** — cards with content thumbnails (text files show their opening lines, images show the picture), plus the same checkboxes and per-card actions. - **Slideshow `▶`** — one large card at a time with a `◀ 1 / N ▶` pager; browsing only, no selection. ![Grid view of a writable directory: content thumbnails on cards, and the Upload File / New Folder / Upload Folder toolbar](media/04-grid-view.png) ## 6. Select entries and use the item menu Tick checkboxes in list or grid view. The toolbar shows `N selected` with two batch actions: **Collect** and **Clear**. Right-clicking a row and clicking its `⋯` button open the **same** menu; on beta.34 it contains exactly one action, **Collect**, which bookmarks the entry into your per-user collection. Collect appears on every entry, including entries in read-only directories. There is **no rename, delete, move, or copy** anywhere in this surface on beta.34 — not in the menu, not in the batch bar. See [Failures to expect](#failures-to-expect). ![List view with two rows selected, the “2 selected · Collect · Clear” batch bar, and the open item menu showing Collect](media/05-list-menu-multiselect.png) ## 7. Write into a writable directory The Explorer probes each directory's writability as you navigate. On directories that probe writable, the toolbar gains **Upload File**, **New Folder**, and **Upload Folder**; on read-only directories these buttons stay hidden. **New Folder** opens an inline name input — type a name and press `Enter`. Whether the write then *succeeds* depends on the mount actually implementing plain writes. Verified failure case: on `/blocklet-manager` (a workspace mount whose declared capabilities do not include `write`), the toolbar appears, the name input accepts and clears — and nothing is created, with no error shown. The same write through the CLI fails explicitly (`ERROR: Internal server error`). Trust the mount's declared capabilities, not the toolbar, before relying on a write. ## 8. Use it on a narrow screen Below roughly phone width the four panes collapse into a tab bar — **sidebar / primary / inspector** — showing one pane at a time. Verified at 390 px width. ## Failures to expect | What you do | What happens on beta.34 | Meaning | |---|---|---| | Paste a deep link into a running session's browser | May land on the last-visited path instead | Load the same URL again; it then resolves correctly | | `New Folder` on a mount without plain `write` support | Input accepted, nothing created, no error | Silent no-op; check the entry's `capabilities` in Details first | | Look for rename / delete / move / copy | Not present in any menu or toolbar | This surface is browse + collect + upload only | | Look for an "execute action" button | Not present; `exec` may still appear under `capabilities` | Action execution is not exposed here — use `arc afs exec`, or the daemon's `/explorer-classic/` route (see [Appendix](#appendix-the-classic-explorer-no-longer-a-separate-command)) | | Select a `registry:` documentation node | `No preview available` + Download | Inline preview depends on the node kind, not the file extension | | Watch the status bar for progress | Always `Ready` | Static text, not a live indicator | ## Appendix: the classic explorer (no longer a separate command) There used to be a second, standalone way to reach this UI: `arc explore [path] --port ` started its own local server independent of any running daemon. That command was removed in ArcBlock/arc#5234 (it registered no automated callers) — but the UI itself did not go away. Every daemon started with `arc service start` now serves it directly at **`/explorer-classic/`** (verified: `curl http://localhost:/explorer-classic` 301-redirects to `/explorer-classic/`, which returns the same `AFS Explorer` page with **Browse / Mounts / Registry** tabs, mount management, and action execution — this is a *different, fuller* surface than the blocklet-served `/explorer` documented above, whose [Failures to expect](#failures-to-expect) table explicitly lacks mount management and action execution). If you have old notes or scripts calling `arc explore`, replace them with `arc service start` and open `http://localhost:/explorer-classic/`. ## What this page does not do - It does not claim your instance shows the same mounts, paths, or children as the screenshots. - It does not document tag authoring — the Tags section was verified only in its empty state. - It does not promise write support on any given mount; capabilities are declared per mount. - It does not cover formal publish or DID Space deployment checks; see [Runtime boundaries](../runtime-boundaries/). --- ## Get started with AFS URL: https://www.arcblock.io/en/docs/afs/getting-started/ Start by checking the runtime you are actually using. Commands and provider availability can vary between ARC releases. ```bash arc --version arc afs --help ``` Verified on `arc` `2.0.0-beta.28`: ```text 2.0.0-beta.28 ``` ```text arc afs AFS file system operations (ls, read, write, stat, exec, search, mount…) Commands: arc afs ls [path] List directory contents [aliases: list] arc afs read Read file content [aliases: cat] arc afs write [content] Write content to file arc afs delete Delete file or directory [aliases: rm] arc afs stat Get file or directory info arc afs exec Execute an action arc afs explain [topic] Explain AFS concepts or paths arc afs search Search for content within an AFS path [aliases: grep, find] arc afs mount Mount management ``` These commands only report the installed version and available AFS command surface. They do not invent mounts or storage for you. ## What to do next 1. Prefer **read-only** inspection first: `ls`, `stat`, `read`, `explain`, and `search` on paths that already exist on your instance. 2. Do **not** begin with `write`, `delete`, or `exec` against an unknown path. A path is meaningful only after the target instance has a provider and mount configuration. 3. Continue with [local inspection](../local-inspection/) for a verified walk of a running instance. 4. Read [the core contract](../core-contract/) before relying on an operation in application code. ## Related CLI man page The full `arc afs` flag reference lives in the [arc-cli board](../../arc-cli/command-reference-afs/). This AFS board explains the path, capability, and provider contract; it does not restate every CLI flag. ## Environment notes - `arc afs` talks to the local AFS surface available to your CLI session (typically a running daemon). Paths and mounts on **your** machine are not universal defaults. - `mount list` can print provider URIs that include credentials. Treat that output as secret material; redact before sharing or pasting into issues. - Adding a mount with `arc afs mount add` may report success while subsequent `ls`/`read` still fail on that path. Confirm with `stat`/`ls` before documenting a new mount as usable. See [Runtime boundaries](../runtime-boundaries/). --- ## Inspect a local AFS surface URL: https://www.arcblock.io/en/docs/afs/local-inspection/ Use this page to inspect a **running local AFS surface** that you already own. All pasted output below was produced with `arc` `2.0.0-beta.28` against a local daemon. Your mounts, paths, and children will differ. Do not treat the sample paths as product defaults. **Safety rules for this walkthrough** | Rule | Why | |---|---| | Prefer `explain`, `ls`, `stat`, `read`, `search` first | They inspect without inventing structure | | Use only paths your instance already exposes | Unknown paths are not a universal demo tree | | Redact secrets from `mount list` | Provider URIs can embed tokens | | Do not run `write`/`delete`/`exec` until you know the mount's access mode | Mutation is mount- and permission-specific | | Do not assume a fresh `mount add` is immediately usable | Verified gap: CLI may report success while ops fail | ## 1. Confirm version and help ```bash arc --version arc afs --help ``` ```text 2.0.0-beta.28 ``` The help text lists `ls`, `read`, `write`, `delete`, `stat`, `exec`, `explain`, `search`, and `mount`. Full flags: [arc afs](../../arc-cli/command-reference-afs/). ## 2. Explain concepts, then mounts ```bash arc afs explain ``` ```text AFS Overview ============ AFS (Agentic File System) is a virtual filesystem that unifies different data sources into a single namespace. Core Concepts: - mount: Mount a data source to a virtual path - path: Virtual path, e.g., /src, /data - uri: Data source address, e.g., fs://, git://, sqlite:// Data Flow: User Path -> AFS -> /{mount} -> Provider -> Actual Data ``` ```bash arc afs explain mount ``` `explain mount` lists **this instance's** mounts. Output is environment-specific. Example shape (paths redacted where sensitive): ```text Mounts ====== Current mount configuration: /dev/ai/hub /dev/web - Web Device — Site Host /ash - ASH pipeline DSL /modules/vault /modules/project /modules/memory … ``` ```bash arc afs mount list ``` Example (credentials redacted): ```text /dev/ai/hub -> aignehub://hub.aigne.io /dev/web -> web-device:// (Web Device — Site Host) /ash -> ash:// (ASH pipeline DSL) /modules/vault -> vault://…[redacted] /modules/project -> fs:///…/project /modules/memory -> fs:///…/test-mem /telegram -> telegram://[REDACTED] … ``` ```bash arc afs mount validate ``` ```text Configuration is valid ``` `validate` checks configuration shape. It does not prove every mount can serve data. ## 3. List the root namespace ```bash arc afs ls / -l ``` Sample (truncated; your root entries differ): ```text ├── 📁 blocklet-manager — Local blocklet workspace manager: … ├── 📁 spaces — Local DID Space logical roots ├── 📁 web — Web Device — renders .web/ + pages/ into static HTML. … ├── 📁 registry ├── 📁 modules ├── 📁 .knowledge (afs:system) — Provider capability index ├── 📁 .meta (afs:system) — Root metadata and mount info └── 📁 .actions (afs:system) — Root-level executable actions ``` ```bash arc afs stat / ``` ```text PATH=/ CHILDREN=108 ACTIONS=mount,unmount,read,list,write,query,aggregate,delete ``` Root `ACTIONS` advertise root-level actions. A listed action name is not a promise that every mount supports the same verb. ## 4. Inspect a known mount path Pick a path that already appears under your root or in `mount list`. On the verification host, `/modules/project` was a local `fs://` mount. ```bash arc afs ls /modules arc afs stat /modules/project arc afs explain /modules/project ``` ```text PATH=/modules/project KIND=fs:directory CHILDREN=185 MODIFIED=2026-07-30T21:14:23.150Z ``` ```bash arc afs read /modules/project/package.json --start-line 1 --end-line 12 ``` ```text { "name": "afs", "description": "Explore and manage AFS file systems", "version": "2.0.0-beta.15", … } ``` ## 5. Read declared capabilities on a path When a provider exposes them, capabilities live under `/.meta/.capabilities` relative to the mount (or aggregated views). ```bash arc afs read /modules/project/.meta/.capabilities ``` Truncated, verified shape for the local `fs` mount: ```json { "schemaVersion": 1, "provider": "fs", "description": "Local filesystem provider", "operations": { "read": true, "list": { "supported": true, "features": { "orderBy": true } }, "write": { "supported": true, "features": { "ifMatch": true, "treeMerge": true, "treeToggle": true, "treeIncrement": true } }, "delete": { "supported": true, "features": { "where": true } }, "search": true, "exec": true, "stat": true, "explain": true, "batchWrite": true, "batchDelete": true } } ``` Use this declaration—not a guess from path shape—to decide whether `search`, `write`, or batch ops are in contract. ## 6. Search (provider-defined free text) ```bash arc afs search /modules/project RELEASING ``` Sample hits (truncated): ```text /modules/project/CLAUDE.md /modules/project/README.md /modules/project/RELEASING.md … ``` Search quality, coverage, and ranking are provider-defined. See [Search and query](../search-and-query/). ## 7. Failures to expect | Command | Observed on beta.28 | Meaning | |---|---|---| | `arc afs read /this-path-does-not-exist-xyz` | `ERROR: Path not found: …` (exit `5`) | Missing path | | `arc afs ls /modules/project/definitely-missing-xyz` | `ERROR: Path not found: …` (exit `5`) | Missing child under a mount | | `arc afs exec /.actions/query --args '{"path":"/modules/project","limit":2}'` | `ERROR: Collection query is not available on this surface` (exit `5`) | Query not declared / not available here — not a silent list fallback | | `arc afs mount add /modules/… fs:///tmp/…` then `ls`/`read` | Mount message prints success; `explain` may show `TYPE unknown`; `ls` empty or error; `read` not found | Do not treat add success as operational readiness without re-checking | ## 8. Optional: mutate only on a known writable mount If—and only if—you have a writable mount you control (for example a disposable directory already mounted as `fs://`), you can exercise write/read/delete. Do not invent a universal writable path. Verified on a pre-mounted writable `fs://` path (`/modules/memory` on the verification host — **your path will differ**): ```bash arc afs write /modules/memory/afs-doc-recipe.txt --content 'Hello from AFS recipe' --mode create arc afs read /modules/memory/afs-doc-recipe.txt arc afs stat /modules/memory/afs-doc-recipe.txt arc afs delete /modules/memory/afs-doc-recipe.txt ``` ```text OK /modules/memory/afs-doc-recipe.txt Hello from AFS recipe PATH=/modules/memory/afs-doc-recipe.txt KIND=fs:file SIZE=21 … delete ``` After delete, read fails with not-found. Full task form: [Recipes](../recipes/). ## What this page does not do - It does not start or reconfigure your daemon for you. - It does not claim a single demo tree ships with every install. - It does not treat repository package names as mounted products. - It does not substitute for formal publish or DID Space deployment checks. Local inspection is a different verification surface; see [Runtime boundaries](../runtime-boundaries/). --- ## AFS URL: https://www.arcblock.io/en/docs/afs/overview/ AFS is ARC's path-addressable filesystem abstraction. A provider supplies resources and declares the operations it supports. ARC routes an operation to the provider that owns the path. Treat a path as an interface boundary, not evidence that all data lives in one store. A provider decides how it reaches or stores its own data. AFS does not require a client to copy every resource into one shared repository before addressing it. ## Path routing A caller issues an operation on an AFS path. The runtime matches the path to a mount, then hands the operation to that mount's provider. The provider executes only the operations it implements and enforces. | Stage | Role | |---|---| | Caller | CLI (`arc afs`), RPC, agent tool, or application code | | AFS path | Virtual address in the instance namespace (for example `/modules/project`) | | Mount route | Match the path prefix to a mounted provider | | Provider | Capability gate and operation implementation | | Backing system | Provider-owned store or transport | ![Flow from caller through AFS path and mount routing to a provider and its backing system](https://raw.githubusercontent.com/ArcBlock/loop-agent-assets/main/arcblock-site/docs-afs-20260810/afs-path-routing-20260811071326.svg) ## Start with the contract, not a storage assumption The core API includes operations for listing, reading, writing, deleting, renaming, inspecting, searching, executing, explaining, and optional batch forms. A provider can expose only the operations it implements. Check the provider's declared capability before making an operation part of an application contract. | Need | Read next | |---|---| | Inspect the installed command surface without changing data | [Get started](../getting-started/) | | Walk a real local instance with verified command output | [Local inspection](../local-inspection/) | | Understand the operations and their capability boundary | [Core contract](../core-contract/) | | Keep enumeration, structured query, and free-text search separate | [Search and query](../search-and-query/) | | Use or implement a provider | [Providers](../providers/) | | Look up a term or run a repeatable task | [Reference](../reference/) · [Recipes](../recipes/) | ## What this page does not promise AFS does not make every provider searchable, writable, or executable. In particular, a provider defines its search coverage, index strategy, and relevance or ranking. ARC returns matches in a shared `AFSSearchResult` envelope and may merge results from searchable providers routed beneath the requested path. Do not assume that this produces a global full-text index, a semantic index, or one uniform ranking across providers. `query` is a separate optional collection capability at `/.actions/query`. A provider that declares the standard query action must execute the complete typed specification; ARC does not turn an unsupported provider into a query provider with a client-side fallback. A package present under `providers/` in the ARC source tree is implementation inventory, not a public support catalog. See [Provider catalog](../provider-catalog/). ## Version boundary Facts and command samples on this board were checked against `arc` `2.0.0-beta.28` and ARC source `44fbd616f` unless a page names another boundary. When you use another release, re-run the commands on that release before treating the pasted output as authoritative. --- ## afs/overview/visuals URL: https://www.arcblock.io/en/docs/afs/overview/visuals/ --- ## Provider catalog URL: https://www.arcblock.io/en/docs/afs/provider-catalog/ This page defines **tiers** for talking about providers. It is intentionally not a generated list of every package under `providers/`. A recent ARC tree inventory observed on the order of **77** provider packages (implementation count, not a support promise). Most of them must stay out of the public catalog until they meet the evidence bar. ## Tiers | Tier | What belongs there | Evidence required before public wording | |---|---|---| | **Core runtime contract** | Shared path, operation, capability, and error contracts every author must understand | Current source + contract tests. This board documents those contracts; it does **not** list individual providers as "core products" | | **Reference / optional (documented)** | A named integration you may present to developers as a starting point or optional module | Complete [authoring acceptance record](../author-a-provider/): contract, access boundary, conformance result, isolated local acceptance, compatibility, support ownership | | **Source inventory only** | Packages visible in ARC source, including experimental, test-oriented, or incomplete work | Package presence alone. Keep source notes separate from the public catalog | | **Do not list** | Internal, abandoned, or unverified backends; anything whose search/auth story would mislead | — | ## Verified-with-evidence entries (this board revision) Entries below are **not** a complete product matrix. Each row cites the evidence used for this revision (`arc` `2.0.0-beta.28` and/or ARC `44fbd616f`). Absence from the table means "not admitted here yet," not "does not exist in source." ### Core / reference evidence (not full product acceptance) Rows below are **core-contract or reference baselines with the evidence cited**. They are **not** a claim that every field of the [authoring acceptance record](../author-a-provider/) is already on file as a product support commitment (owner, lifecycle, isolated demo pack, public support surface). Use them to start from, not as a finished “admitted product” matrix. | Name | Role | Evidence | Limits | |---|---|---|---| | **JSON / YAML provider** (`@aigne/afs-json`, `providers/core/json`) | Compact tree-as-FS baseline for authors | Conformance: `pnpm --filter @aigne/afs-json test -- test/conformance.test.ts` → **372 pass, 6 skip, 0 fail** on ARC `44fbd616f`. Source implements list/read/write/delete/search/stat/explain (+ rename in capabilities when writable) | Local file-backed JSON/YAML; not a remote multi-tenant store; search is provider-local over that tree; **not** a complete product acceptance record | | **Local filesystem provider** (`providers/basic/fs`, URI scheme `fs://`) | Common local directory mount | Live local acceptance on beta.28: `ls`/`stat`/`read`/`search` on a mounted project tree; `read …/.meta/.capabilities` shows `provider: "fs"` with write/search/exec/batch flags; disposable write/read/delete on a separate pre-mounted writable `fs://` path | Instance-specific mounts; `mount add` success ≠ immediate operational readiness (see [Runtime boundaries](../runtime-boundaries/)); search is filesystem search for that mount, not global FTS | ### Observed on a sample daemon (not catalog admission) The following appeared on **one** verification host's `mount list` / root listing. They illustrate environment mounts only. They are **not** elevated to supported public products by this page: - `web-device://` (Web Device site host — contract lives on the [Web Device board](../../web-device/)) - `vault://`, agent `code-agent://` mounts, messaging mounts, hub URIs, and others Do not copy a host's mount list into marketing or onboarding as "supported providers." ## Admission rule (repeat) Do not promote a provider because the backend name is familiar or because a package exists. A future catalog row must name version boundary, supported operations, access/data boundary, maintainer, docs location, and the exact local acceptance evidence used. Until more rows meet that rule, this catalog stays intentionally thin. --- ## Providers URL: https://www.arcblock.io/en/docs/afs/providers/ An AFS provider is an `AFSModule` that supplies resources and operations behind paths. It is the unit that decides which operations exist, how paths resolve, and how a backing system is reached. ## Role in routing | Step | Who owns it | |---|---| | Path string in the instance namespace | Caller | | Mount path → provider instance | Runtime / configuration | | Operation implementation and enforcement | Provider | | Backing store or network transport | Provider | Without a mount that maps a path prefix to a provider, the path is not a product feature—it is an unresolved address. See the routing diagram on [Overview](../overview/). ## What a provider must make explicit Provider documentation (or acceptance records) should state: | Topic | Why it matters | |---|---| | Owned path shape | How callers form stable paths | | Declared operations and features | What is in contract vs optional | | Access mode / auth / network-read policy | Who may read or mutate | | Search and query behavior | Separate contracts; see [Search and query](../search-and-query/) | | Failure codes and side effects | What callers can branch on | | Support ownership | Who maintains it | ## Source inventory is not a catalog The current ARC repository groups provider packages under areas such as core, basic, AI, messaging, platform, runtime, cost, IoT, and test. That inventory is **implementation evidence**. A package directory does not by itself become a stable public integration. This board therefore: - Explains the module contract on [Author a provider](../author-a-provider/) - Defines admission tiers on [Provider catalog](../provider-catalog/) - Does **not** flatten every package as an equally supported product ## Runtime modules you may already see On a local daemon, `arc afs ls /` and `mount list` show **this instance's** mounts—not the full source inventory. Examples observed on one beta.28 host (not a support matrix): `fs://` project and memory trees, `web-device://`, `vault://`, agent code mounts, and others. Treat them as environment-specific until a catalog entry with evidence exists. --- ## AFS recipes URL: https://www.arcblock.io/en/docs/afs/recipes/ Each recipe names its version, mutation risk, and assumptions. Paths like `/modules/project` are **examples from the verification host**, not universal defaults. Substitute mounts from your own `arc afs mount list`. **Version:** `arc` `2.0.0-beta.28` ## Recipe 1 — Read-only root and mount survey **Goal:** Learn what this instance exposes without changing data. **Mutates:** No **Assumes:** Local CLI can reach your AFS surface (typically a running daemon) ```bash arc --version arc afs explain arc afs mount list # redact secrets before sharing arc afs mount validate arc afs ls / -l arc afs stat / arc afs ls /.actions ``` **Observed (truncated, host-specific):** ```text 2.0.0-beta.28 ``` ```text Configuration is valid ``` ```text PATH=/ CHILDREN=108 ACTIONS=mount,unmount,read,list,write,query,aggregate,delete ``` ```text /.actions/unmount /.actions/read /.actions/list /.actions/write /.actions/query /.actions/aggregate /.actions/delete /.actions/mount ``` **Done when:** You can name at least one mount path you are willing to inspect further. --- ## Recipe 2 — Inspect a known mount (list / stat / read / capabilities / search) **Goal:** Verify routing and capabilities on one existing mount. **Mutates:** No **Assumes:** A mount already serves data (verification host used `/modules/project` → `fs://…`) ```bash MOUNT=/modules/project # replace with your path arc afs ls "$MOUNT" arc afs stat "$MOUNT" arc afs explain "$MOUNT" arc afs read "$MOUNT/.meta/.capabilities" arc afs search "$MOUNT" RELEASING ``` **Observed (truncated):** ```text PATH=/modules/project KIND=fs:directory CHILDREN=185 MODIFIED=2026-07-30T21:14:23.150Z ``` Capabilities JSON included `"provider": "fs"` with `search: true` and write features such as `ifMatch` (full blob on [local inspection](../local-inspection/)). Search returned paths under the mount, for example `/modules/project/RELEASING.md`. **Failure check:** ```bash arc afs read /this-path-does-not-exist-xyz # ERROR: Path not found: /this-path-does-not-exist-xyz (exit 5) ``` **Done when:** You know whether `search`/`write` appear in that mount's capabilities and you have read one real file. --- ## Recipe 3 — Disposable write / read / delete on a pre-mounted writable path **Goal:** Exercise mutation only where you already have a writable mount. **Mutates:** Yes (creates and deletes one file) **Assumes:** An **already mounted** writable path you control. On the verification host this was `/modules/memory` (`fs://…/test-mem`). **Do not** copy that path blindly. **Does not assume:** That `arc afs mount add` just succeeded—see [Runtime boundaries](../runtime-boundaries/). ```bash W=/modules/memory/afs-doc-recipe.txt # replace prefix with YOUR writable mount arc afs write "$W" --content 'Hello from AFS recipe' --mode create arc afs read "$W" arc afs stat "$W" arc afs write "$W" --content ' — append' --mode append arc afs read "$W" arc afs delete "$W" arc afs read "$W" # expect not found ``` **Observed:** ```text OK /modules/memory/afs-doc-recipe.txt Hello from AFS recipe PATH=/modules/memory/afs-doc-recipe.txt KIND=fs:file SIZE=21 MODIFIED=2026-08-11T06:47:04.762Z OK /modules/memory/afs-doc-recipe.txt Hello from AFS recipe — append delete ERROR: Path not found: … ``` **Optional negative checks (do not invent success):** ```bash MOUNT=/modules/project # replace with your path (recipe stands alone; do not rely on Recipe 2) arc afs exec /.actions/query --args "{\"path\":\"$MOUNT\",\"limit\":2}" # On the verification fs mount: ERROR: Collection query is not available on this surface ``` **Done when:** Create, read, append, and delete all behaved as expected on **your** mount, and the disposable file is gone. --- ## Recipe hygiene | Rule | Reason | |---|---| | Name `arc --version` in any shared runbook | Commands drift across betas | | Prefer pre-existing mounts for demos | Avoid unproven `mount add` paths | | Redact `mount list` | Credentials appear in URIs | | Separate list / search / query | Different contracts | | Clean up disposable files | Leave the instance as you found it | --- ## AFS reference URL: https://www.arcblock.io/en/docs/afs/reference/ Version boundary for pointers on this page: ARC source layout as of `44fbd616f`, CLI `arc` `2.0.0-beta.28`. Paths under `packages/` and `providers/` refer to the ARC repository (read-only reference for site authors), not to files inside this site blocklet. ## Terminology | Term | Meaning | |---|---| | **AFS** | Path-addressable filesystem abstraction in ARC | | **Path** | Virtual address in an instance namespace (for example `/modules/project/README.md`) | | **Mount** | Binding from a path prefix to a provider URI/instance | | **Provider / `AFSModule`** | Module that implements operations for owned paths | | **Capability / operations declaration** | What ops (and features) the provider claims to support | | **`list`** | Enumerate children; best-effort options | | **`search`** | Provider-defined free-text retrieval | | **`query`** | Optional strict typed collection query at `/.actions/query` | | **`exec`** | Invoke an action at an executable path | | **`explain`** | Describe concept or path resolution | | **Access mode** | `readonly` / `create` / `append` / `readwrite` | | **Visibility** | `full` / `meta` | | **Conformance** | Shared provider tests via `@aigne/afs-testing` | | **Instance** | A concrete runtime with its own mounts and data | ## Core types and ops (source pointers) | Topic | Where in ARC | |---|---| | `AFSModule`, `AFSRoot`, entry/result types | `packages/core/src/type.ts` | | Dispatcher / routing | `packages/core/src/afs.ts` | | `OperationsDeclaration`, capability helpers | `packages/core/src/capabilities/types.ts` | | Collection query types + strict validator | `packages/core/src/capabilities/collection-query.ts` | | Error classes and codes | `packages/core/src/error.ts` | | Base provider + decorators | `packages/core/src/provider/` | | JSON reference provider | `providers/core/json/` | | FS provider | `providers/basic/fs/` | | Conformance runner | `packages/testing/` (`runProviderTests`) | | Authoring guide | `docs/guides/provider-authoring.md` | | Collection query guide | `docs/guides/collection-query.md` | ## CLI command group | Command | Role | |---|---| | `arc afs ls` | List | | `arc afs read` | Read | | `arc afs write` | Write | | `arc afs delete` | Delete | | `arc afs stat` | Stat | | `arc afs search` | Search | | `arc afs exec` | Exec action | | `arc afs explain` | Explain | | `arc afs mount …` | Mount management | Full flag reference: [arc afs](../../arc-cli/command-reference-afs/). ## Board map | Page | Question | |---|---| | [Overview](../overview/) | Abstraction and non-promises | | [Get started](../getting-started/) | First command surface | | [Local inspection](../local-inspection/) | Verified inspect walk | | [Core contract](../core-contract/) | Ops, capabilities, errors | | [Search and query](../search-and-query/) | list vs query vs search | | [Providers](../providers/) | Provider role | | [Author a provider](../author-a-provider/) | Implementation start | | [Provider catalog](../provider-catalog/) | Tiered public listing | | [Runtime boundaries](../runtime-boundaries/) | Mounts, state, local vs publish | | [Recipes](../recipes/) | Repeatable tasks | ## Related boards - [AUP](../../aup/) — declarative UI model - [Web Device](../../web-device/) — static site provider over AFS paths - [arc-cli](../../arc-cli/) — command man pages ## Error codes (quick index) See the table on [Core contract](../core-contract/). Branch on codes such as `AFS_NOT_FOUND`, `AFS_UNSUPPORTED`, `AFS_VALIDATION_ERROR`, `AFS_CONFLICT`, `AFS_READONLY`, `AFS_AUTH_REQUIRED`. --- ## Runtime boundaries URL: https://www.arcblock.io/en/docs/afs/runtime-boundaries/ AFS behavior is always **instance-shaped**. The same CLI binary against two daemons, two `ARC` data directories, or two mount tables will not produce the same paths. Verified with `arc` `2.0.0-beta.28` against a local daemon unless noted. ## Mounts | Fact | Detail | |---|---| | Mount binds a path prefix to a provider URI | Example shape: `/modules/project -> fs:///absolute/path` | | List mounts | `arc afs mount list` / `arc afs explain mount` | | Validate config shape | `arc afs mount validate` → `Configuration is valid` on the verification host | | Secrets | URIs may embed credentials (tokens, vault paths). Redact before sharing | ### `mount add` is not automatically an acceptance path On beta.28, the following sequence was observed: 1. `arc afs mount add /modules/… fs:///tmp/…` printed `Mounted …`. 2. `arc afs mount list` showed the new row. 3. `arc afs explain ` reported `TYPE unknown`. 4. `ls` returned empty or connection errors; `read` returned not found. 5. `arc afs mount remove ` cleared the list entry. **Do not** document a recipe that assumes add-then-immediately-write succeeds on every host. Prefer: - inspecting mounts that are already serving data, or - an isolation procedure your team has verified end-to-end (separate data dir / service instance), then re-check with `stat`/`ls` before mutation. ## Permissions and access | Layer | What it constrains | |---|---| | Provider `accessMode` | `readonly` / `create` / `append` / `readwrite` | | `visibility` | `full` vs `meta` (meta denies search content) | | Action severity / policy | Which `exec` actions may run | | Caller / network gates | Auth and network-read rules on some mounts | A root that lists `write` among root actions still does not make every child mount writable. ## Instance state | Kind of state | Examples | Doc implication | |---|---|---| | Process | Running daemon PID/port under the host's AFS data dir | CLI often talks to this daemon | | Mount table | Configured provider URIs | Environment-specific | | Provider data | Files under an `fs://` path, vault contents, remote resources | Mutation changes real data | | Blocklet / space data | Under local DID Space trees | Different board; do not treat as disposable | Do not treat an arbitrary long-lived daemon as disposable test infrastructure. Commands that register mounts or write provider data need a deliberate isolation story. ## Local validation vs formal publish | Surface | What it proves | What it does not prove | |---|---|---| | Local `arc afs …` against your daemon | This instance's path/ops/mount behavior | Global product defaults, multi-tenant deploy | | Local blocklet service / browser (site docs) | Site rendering of documentation | Remote DID Space hosting of your app | | `arc deploy` / DID Space publish | Publish integration when that is the task | Local AFS contract correctness by itself | | Provider conformance tests in ARC monorepo | Provider interface discipline at a commit | That your host's mounts match that provider | For this AFS board, **local inspection and recipes are the primary evidence**. Formal publish is a separate checklist—use it only when the task is deployment. ## Practical checklist 1. Record `arc --version`. 2. Prefer read-only commands until mounts and capabilities are known. 3. Read `/.meta/.capabilities` when present. 4. Mutate only on mounts you own; clean up disposable paths. 5. Redact secrets from any shared output. 6. When a command fails, preserve the exact error—do not invent success output. --- ## Search and query URL: https://www.arcblock.io/en/docs/afs/search-and-query/ Do not use `list`, `query`, and `search` as names for the same feature. They solve different problems and make different promises. Evidence: `packages/core/src/capabilities/collection-query.ts`, `docs/guides/collection-query.md`, `AFSModule.search` / `query` in `type.ts`, and CLI runs on `arc` `2.0.0-beta.28`. ## Three contracts | Operation | Use it for | Do not assume | |---|---|---| | `list` | Enumerating paths or entries under a path | A relevance-ranked result set, or a provider-independent data query language | | `query` | A typed collection specification at the standard `/.actions/query` action | Client-side fallback when a provider has not declared the capability | | `search` | Provider-defined free-text retrieval returned in a shared result envelope | Universal full-text coverage, semantic retrieval, a shared index, or one ranking algorithm | ### list — best-effort enumeration `list` is the filesystem-style directory walk. Unsupported options may be ignored or marked (for example order-by ignored metadata). It is the right tool for "what children exist here?" ```bash arc afs ls /modules/project ``` ### search — provider-defined free text ```bash arc afs search ``` Verified sample on a local `fs://` mount (`arc` `2.0.0-beta.28`): ```bash arc afs search /modules/project RELEASING ``` ```text /modules/project/CLAUDE.md /modules/project/README.md /modules/project/RELEASING.md … ``` | Rule | Detail | |---|---| | Ownership | The provider owns what it searches, how it indexes, and how it ranks | | Envelope | ARC returns matches in `AFSSearchResult` and can merge searchable providers under the requested path | | No global promise | Merging results is not a global FTS index or semantic search product | | Visibility | On `visibility: "meta"` mounts, search is denied | Document search expectations in the **provider's** docs, not by copying behavior observed on a different provider. ### query — optional and strict Collection query is the typed action at `/.actions/query` (entries mode and aggregate mode). Philosophy is **declare ⇒ execute the whole spec**. Malformed specs and unsupported blocks are `AFS_VALIDATION_ERROR` (or equivalent). There is no silent client-side degradation to "sort of query via list". Probe before relying on it: read `/.meta/.capabilities` (or root capabilities) and look for the standard action with `name === "query"` and `pathTemplate === "/.actions/query"`. Provider-local dialects (for example table-scoped query paths) are not this contract. Verified on beta.28 against an `fs://` project mount that does **not** offer collection query on this surface: ```bash arc afs exec /.actions/query --args '{"path":"/modules/project","limit":2}' ``` ```text ERROR: Collection query is not available on this surface ``` Exit code observed: `5`. That failure is the correct signal—not a partial list of files. When a provider **does** declare query, a consumer issues a typed spec (fields such as `path`, `doc`, `where`, `orderBy`, `limit`/`offset` or cursor, `count`, `groupBy`, optional aggregate ops). Full field vocabulary and provider implementation checklist live in ARC's internal guide `docs/guides/collection-query.md` and `packages/core/src/capabilities/collection-query.ts`. ## Choosing among the three | Goal | Prefer | |---|---| | Browse a tree | `list` | | Find free-text matches the provider knows how to find | `search` (after checking capability) | | Server-side typed filter / order / count / aggregate over a record collection | `query` (only if declared) | | "Search everything on the machine like a desktop FTS product" | **Out of contract** for AFS as a whole | ## Product narrative caution A future document library or NAS-oriented product may still layer catalogs, selected full-text collections, and richer indexes as **separate product choices**. Those choices are not automatic consequences of using AFS paths. --- ## Agent Access URL: https://www.arcblock.io/en/docs/agent-access/ --- ## Access tiers URL: https://www.arcblock.io/en/docs/agent-access/access-tiers/ Whether a call succeeds is decided by four gates, in this order. They are independent: clearing one says nothing about the next. The most common mistake is assuming a credential is enough. It clears gate 2. Gates 3 and 4 still apply, and on a blocklet that has declared no network rules they will still refuse a write from an owner-role caller. | # | Gate | Decided by | Failure looks like | |---|---|---|---| | 1 | Method allowlist | Whether the JSON-RPC method is anonymous-safe | `401` + `WWW-Authenticate` | | 2 | Credential | The bearer token or session cookie you sent | `401` + `WWW-Authenticate` | | 3 | Path policy | What the **blocklet** declared for that path | `200` with `isError` and `AFS_FORBIDDEN` | | 4 | Provider capability | What the provider behind the path implements | `200` with `isError` and a not-supported error | Gates 1 and 2 are transport-level: they answer with an HTTP status and no JSON-RPC result. Gates 3 and 4 are inside a successful MCP call: the call itself worked, the operation did not. See [Errors](../errors/). ## Why there are four Because three different parties decide them, and none can answer for another. | Gate | Decided by | What it is really asking | |---|---|---| | 1, 2 | The runtime | Is this method safe without a caller, and is this caller who they say they are? | | 3 | The blocklet | Have I opened this path to the network? | | 4 | The provider | Do I implement this operation at all? | This is why a credential is not enough, and why no better credential would help. A credential is an answer to the runtime, and the runtime does not own gates 3 and 4. No token can speak for the blocklet, and none can add an operation the provider never implemented. It also explains the failure shapes. Gates 1 and 2 are decided before a tool is reached, so they can only answer in HTTP. Gates 3 and 4 are decided by code that already ran, so they answer inside a `200`. ## Gate 1: the method allowlist Without a credential, only these are allowed: | Allowed anonymously | Not allowed anonymously | |---|---| | `initialize`, `notifications/initialized` | `tools/call` with `afs_write`, `afs_delete`, `afs_exec` | | `tools/list`, `resources/list`, `prompts/list` | Any other method, including unknown ones | | `tools/call` with `afs_read`, `afs_list`, `afs_search`, `afs_stat`, `afs_explain`, `search_content`, `list_content`, `get_content` | | The rule is fail-closed: anything not on the list is refused, and in a batch every message must be allowed or the whole batch is refused. ## Gate 2: the credential Three ways to clear it: | Tier | Credential | Where it comes from | |---|---|---| | Anonymous | none | n/a | | Authenticated | `Authorization: Bearer blocklet-…` or a DID-Connect session cookie | [Authorize a client](../authorize-a-client/) or [the device grant](../device-grant/) | | Loopback operator | verified same-machine socket peer, Node runtime only | Nothing to obtain. Never available over the network; the Cloudflare runtime never grants it | ### Roles When a person approves a client, the consent screen asks for an **access level**. Four are offered: | Role | | |---|---| | `owner` | the default on the consent screen | | `admin` | | | `member` | | | `guest` | | The credential carries the role the person picked, scoped to that blocklet instance. It is not a global role: the same person can be `owner` on one blocklet and have no access on another. **The role is an upper bound, not a grant.** It cannot open a path that gate 3 has closed. ## Gate 3: the path policy This is the gate most callers hit and the one no credential can bypass. A blocklet decides, per path, what a **network** client may do. Paths that were not declared are closed to the network, including to an owner. The refusal is explicit about the fix: ```json { "result": { "content": [{ "type": "text", "text": "AFS_FORBIDDEN: Forbidden at /instance/notes.txt: network clients cannot write base paths; use a resolver overlay or internal code" }], "isError": true }, "jsonrpc": "2.0", "id": 3 } ``` Read and list produce the same shape with `cannot read base paths` / `cannot list base paths` and `declare a networkRead rule or use an overlay`. What the declaration changes, compared across two blocklets: | Call | Blocklet that declares nothing | Blocklet that declares collections with `readRole: guest` | |---|---|---| | anonymous `afs_list /` | refused | **200** | | anonymous `afs_list /packages` | refused | **200** | | anonymous `afs_list /.knowledge` | refused | refused, because that path was not declared either | | anonymous `list_content` on a declared collection | tool not registered | **200** | | **owner-credential `afs_write` on any base path** | **refused** | **refused** | The last row is the one to remember. Writing from the network is not something a credential turns on; it needs a resolver overlay or code running inside the blocklet. If you are building an agent that must write, that is a decision for whoever owns the blocklet. See [Declare what agents see](../declare-what-agents-see/). ## Gate 4: provider capabilities Each path is served by a provider that implements only some operations. `afs_stat` reports both what the provider can do and what you are allowed to do: ```json { "capabilities": ["list", "read", "stat", "search", "write", "delete", "exec", "explain"], "accessMode": "readonly" } ``` `capabilities` is the provider's implementation. `accessMode` is your effective access after gate 3. A path can list `write` in `capabilities` and still be `readonly` for you. Check `capabilities` before making an operation part of an integration. See [AFS](../../afs/core-contract/) for the contract these operations belong to. ## What this means in practice - **Reading published content works without any credential** when the blocklet declared it. That is the intended path for most agents, and it is what the content tools are for. - **Getting a credential is worth doing** when you need a specific person's view of the data, or when the blocklet has opened write paths to the network. - **A credential is not a write switch.** If writes are refused after you authenticate, gate 3 is the reason and the blocklet owner is the only one who can change it. --- ## AFS over HTTP URL: https://www.arcblock.io/en/docs/agent-access/afs-over-http/ A client that cannot speak MCP can reach the same AFS operations over plain JSON-RPC at `/api/afs/rpc`. It is the same data plane and the same access tiers; only the envelope differs. Use it when the caller is a script, a language without an MCP library, or a model that can issue an HTTP request but has no tool-calling harness. ## Call it ```bash curl -s -X POST https:///api/afs/rpc \ -H 'Content-Type: application/json' \ -d '{"type":"list","path":"/"}' ``` ```json { "ok": true, "data": [ { "id": "instance", "path": "/instance", "summary": "DID-scoped persistent storage with CID-based content deduplication…", "meta": { "childrenCount": -1 } } ] } ``` The request names an operation in `type` and its arguments alongside. Responses are wrapped in `{ "ok": …, "data": … }`. No credential was sent in the request above; anonymous read works here exactly as it does on `/mcp`. ## Inspect a path before you read it `stat` returns what a provider will actually accept, which saves a round of failed calls: ```bash curl -s -X POST https:///api/afs/rpc \ -H 'Content-Type: application/json' \ -d '{"type":"stat","path":"/packages"}' ``` ```json { "ok": true, "data": { "id": "arcblock", "path": "/packages", "meta": { "kind": "did-space:directory", "capabilities": ["list", "read", "stat", "search", "write", "delete", "exec", "explain"], "accessMode": "readonly", "projection": { "base": "arcblock" } } } } ``` `capabilities` is what the provider implements. `accessMode` is what this caller gets. The two are separate: a provider can implement `write` while the path is `readonly` for you. Read `capabilities` before making an operation part of your integration; a provider is not required to implement all of them. See [AFS](../../afs/core-contract/). ## Relationship to the MCP tools | | `/mcp` | `/api/afs/rpc` | |---|---|---| | Envelope | MCP over streamable HTTP | JSON-RPC | | Operations | `afs_*` tools, plus content tools when declared | AFS operations | | Anonymous read | Yes | Yes | | Writes | Credential required | Credential required | | Discovery | `tools/list` | `stat` and `explain` on a path | Both endpoints are listed in the host's [API catalog](../discovery-surfaces/#api-catalog), pointing at the same service description. Prefer `/mcp` when your client supports it: the tool schemas tell an agent what the arguments are, which `stat` does not. ## Writes Writes over this endpoint follow the same rules as `/mcp`: a credential is required, and the blocklet must have published the path to network clients. See [Access tiers](../access-tiers/). The full operation set and its argument shapes belong to the [AFS](../../afs/) contract. --- ## Authorize a client URL: https://www.arcblock.io/en/docs/agent-access/authorize-a-client/ A client that receives `401` with a `WWW-Authenticate` challenge has everything it needs to reach the authorization server. Every step is a plain `GET` or `POST` against the same host. Replace `` with the blocklet's host. | Step | Request | Result | |---|---|---| | 1 | `tools/call` a write tool, no credential | `401` + `WWW-Authenticate` carrying the metadata URL | | 2 | `GET /.well-known/oauth-protected-resource` | Which authorization server protects this resource | | 3 | `GET /.well-known/oauth-authorization-server` | Endpoints, grant types, PKCE method | | 4 | `POST /.well-known/service/oauth/register` | A `client_id` for this client | | 5 | Authorize, then exchange for a credential | `Authorization: Bearer blocklet-…` | ## Step 2: protected resource ```bash curl -s https:///.well-known/oauth-protected-resource ``` ```json { "resource": "https:///mcp", "authorization_servers": ["https://"] } ``` The authorization server is the same host. A blocklet protects only its own resource and issues only its own credentials, so a client that talks to several blocklets registers and authorizes with each one separately. ## Step 3: authorization server metadata ```bash curl -s https:///.well-known/oauth-authorization-server ``` ```json { "issuer": "https://", "authorization_endpoint": "https:///.well-known/service/oauth/authorize", "registration_endpoint": "https:///.well-known/service/oauth/register", "device_authorization_endpoint": "https:///.well-known/service/oauth/device_authorization", "token_endpoint": "https:///.well-known/service/oauth/token", "response_types_supported": ["code"], "grant_types_supported": [ "urn:ietf:params:oauth:grant-type:device_code", "authorization_code", "refresh_token" ], "code_challenge_methods_supported": ["S256"], "token_endpoint_auth_methods_supported": ["none"], "scopes_supported": ["mcp"] } ``` `token_endpoint_auth_methods_supported` is `none`, so a client authenticates the token request with its PKCE verifier rather than a client secret. `scopes_supported` has one entry, so there is no narrower or broader scope to choose between. ## Step 4: register the client A client obtains its `client_id` by registering itself. No pre-shared identifier is handed out. ```bash curl -s -X POST https:///.well-known/service/oauth/register \ -H 'Content-Type: application/json' \ -d '{ "client_name": "my agent", "redirect_uris": ["http://127.0.0.1:3118/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none" }' ``` ```json { "client_id": "b665f46e-8fb5-4bf9-bd32-53df5b35f7f5", "redirect_uris": ["http://127.0.0.1:3118/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none" } ``` The response echoes the registration, not just the identifier. Clients validate this and reject a reply that omits fields they sent. **Register once and keep the `client_id`.** Registration is rate limited per source address, and a registration never used in a completed authorization is swept after seven days. ### Redirect URIs A client running on the user's machine listens on a port chosen at run time, so register the exact `redirect_uris` this session will use rather than expecting a fixed value to be pre-approved. Loopback addresses, `https` URLs, and private-use schemes are accepted; anything else is rejected. See [Errors](../errors/#authorization-flow-failures). ## Step 5: obtain the credential Two grants lead to the same credential. Your tool usually picks one for you, see [Connect your tool](../clients/). | Your client | Grant | |---|---| | Can open a browser and listen on a local port, as most MCP clients do | `authorization_code` with PKCE, using `authorization_endpoint` then `token_endpoint` | | Cannot: a CLI, CI job, or headless agent | The device grant, see [Credentials without a browser](../device-grant/) | Both end at the same `token_endpoint` and return the same credential shape. ### What the credential is The token endpoint returns a bearer token that is also an **access key**: ```json { "access_token": "blocklet-zEJYCdC9awCqxEPLhqreFbwXjqU6Y2BHvKVQAx6kMZfRh", "token_type": "Bearer", "scope": "mcp" } ``` Three things follow from that response, and each matters: - **The `blocklet-` prefix is how the runtime recognises it.** OAuth token and access key are not two mechanisms; they are one credential with one prefix. - **It carries the role the person picked** on the consent screen (`owner`, `admin`, `member`, or `guest`), scoped to this blocklet instance. See [Access tiers](../access-tiers/#roles). - **The device grant returns no `expires_in` and no `refresh_token`.** The authorization server advertises `refresh_token` as a supported grant, but the device flow does not hand one back. ## Use it Send it as a bearer token on `/mcp`: ```bash curl -s -X POST https:///mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'Authorization: Bearer blocklet-…' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' ``` The `401` is gone: the same `tools/call` that was refused before now reaches the tool. ## What the credential leaves closed Reaching the tool is not the same as the operation succeeding. An authenticated write can still come back like this, `200` at the transport layer but refused inside: ```json { "result": { "content": [{ "type": "text", "text": "AFS_FORBIDDEN: Forbidden at /instance/notes.txt: network clients cannot write base paths; use a resolver overlay or internal code" }], "isError": true }, "jsonrpc": "2.0", "id": 3 } ``` An owner-role credential gets the same refusal. Writing from the network is not something a credential turns on. The blocklet must have declared that path open to network clients, via a resolver overlay or code running inside it. If your agent must write, that is a decision for whoever owns the blocklet. Read [Access tiers](../access-tiers/#gate-3-the-path-policy) before designing around it. --- ## Connect your tool URL: https://www.arcblock.io/en/docs/agent-access/clients/ Point your tool at `https:///mcp`, where `` is the domain the blocklet is served at. Adding it needs no credential; signing in takes one browser click and is only needed to go past what the blocklet publishes openly. ## Claude Code Add the server: ```bash claude mcp add --transport http arc https:///mcp ``` Check it: ```bash claude mcp list ``` ```text arc: https:///mcp (HTTP) - ✔ Connected ``` You can now use the read tools. To go further, sign in: ```bash claude mcp login arc ``` Your browser opens a consent screen showing which tool is asking, the verified domain it came from, the account it will act as, and the local port your credential will be delivered to. Pick an **access level** and choose **Authorize**. The command completes on its own. Run it from a real terminal. In a pipe or a CI job it stops with `stdin isn't a terminal`. `claude mcp logout arc` clears the credential. `claude mcp remove arc` removes the server. ## Codex CLI One command adds the server and signs you in: ```bash codex mcp add arc --url https:///mcp ``` It prints the authorization URL, opens your browser for the same consent screen, and finishes: ```text Successfully logged in. ``` Check it: ```bash codex mcp list ``` ```text Name Url Bearer Token Env Var Status Auth arc https:///mcp - enabled OAuth ``` `codex mcp login arc` signs in again later; `codex mcp logout arc` clears it. ## grok Not supported yet. `grok mcp add arc -t http https:///mcp` writes the entry, but the connection fails during the handshake: ```text ✗ handshake failed (… Auth error: OAuth authorization required, when send initialize request) ``` grok asks for authorization before the handshake that would tell it none is needed, and `grok mcp` has no `login` command to complete one. Use the header method below instead. ## Any other tool If your tool can send a custom header, [obtain a credential without a browser](../device-grant/) and pass it directly: ```bash claude mcp add --transport http arc https:///mcp \ --header "Authorization: Bearer blocklet-…" ``` This works with any client that supports headers, and is the way to connect from a server or a CI job where no browser is available. ## After you are connected - Signing in raises what you are allowed to ask for. It does not open write access on its own: a blocklet has to publish a path to network clients before anyone can write to it. See [Access tiers](../access-tiers/). - Which tools you see depends on the blocklet, not on your credential. See [Tools](../tools/). - A credential belongs to one blocklet. Connect to a second one and you sign in again. --- ## Connect a client URL: https://www.arcblock.io/en/docs/agent-access/connect-a-client/ Connect an MCP client to a blocklet by giving it the host URL plus `/mcp`. **`` is the domain the blocklet is served at**, the same one you would open in a browser. If you are unsure you have the right one, `GET https:///.well-known/mcp.json` and check its `url` field: it echoes the endpoint the runtime believes it is serving. ```bash claude mcp add --transport http arc https:///mcp ``` No header and no client id are needed to connect. The endpoint accepts anonymous requests and answers the read tools; a credential is only required once you call a write tool. For the exact commands for Claude Code and Codex CLI, see [Connect your tool](../clients/). ## Confirm it without a client The endpoint is plain HTTP, so `curl` is enough to check a host before you wire up an agent. ```bash curl -s -X POST https:///mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' ``` A blocklet that declares no content collections answers with eight tools: ```text afs_read afs_list afs_write afs_delete afs_search afs_exec afs_stat afs_explain ``` A blocklet that declares content collections answers with those eight plus three more: ```text search_content list_content get_content ``` Which set you get depends on the blocklet's own declaration, not on your credential. See [Tools](../tools/). ## `initialize` is not required The request above sends `tools/list` directly, with no preceding `initialize`, and returns `200`. The endpoint is stateless. It does not issue an `mcp-session-id`, so there is no session for a client to hold, lose, or resynchronise. A client can send a stale session id and the request still succeeds; a runtime restart does not invalidate anything on the client side. This matters for long-lived agents: there is no reconnect handshake to implement. ## What anonymous access gives you The handshake, the three list methods, and the read tools. Write, delete, and exec return `401` with a challenge, and so does any method not on the list. The rule is fail-closed. Whether an allowed read actually returns data is a separate question, decided by what the blocklet declared. Both rules are set out in [Access tiers](../access-tiers/). ## When you need to write Calling a write tool without a credential returns the challenge that starts authorization: ```bash curl -s -i -X POST https:///mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"afs_write","arguments":{"path":"/tmp/x","content":"x"}}}' ``` ```text HTTP/1.1 401 Unauthorized www-authenticate: Bearer resource_metadata="https:///.well-known/oauth-protected-resource" {"error":"Unauthorized"} ``` Follow that URL to continue. See [Authorize a client](../authorize-a-client/). ## Connecting a stdio-only client Clients that speak MCP over stdio and cannot open an HTTP transport need a bridge. Use [`arc mcp`](../../arc-cli/command-reference-mcp/), which bridges stdio to a running local daemon. The bridge is a compatibility path for those clients. If your client supports streamable HTTP, connect to `/mcp` directly and skip it. ## Local runtime Against a local Node runtime, a request from the same machine is a verified socket peer and is granted operator access, so write tools answer without a credential. That is the loopback tier; it does not exist over the network and it is not how a deployed blocklet behaves. Use a remote host to exercise the anonymous and authenticated paths. --- ## Declare what agents see URL: https://www.arcblock.io/en/docs/agent-access/declare-what-agents-see/ The content tools, the per-collection `llms` shards, the sitemap, and the web pages are all projections of one declaration in the blocklet manifest. A collection appears on a surface when, and only when, the declaration names that surface. This page covers the parts of that declaration an agent can observe. For the manifest as a whole, see [Blocklets](../../blocklets/). ## The shape ```yaml collections: docs: scope: /packages indexable: - "content/docs/**/content.md" - "content/docs/**/content.zh.md" readRole: guest defaultLocale: en fields: nav-group: $.nav-group summary: - $.name - $.summary faces: web: true sitemap: true llms: true mcp: [search, list, get] ``` | Key | Decides | |---|---| | `indexable` | Which files belong to the collection | | `readRole` | Whether a caller without a credential can read it | | `fields` | Which front matter becomes a filter on the content tools | | `summary` | Which front matter appears in a result, and in what order | | `faces` | Which surfaces the collection reaches | ## Faces are opt-in and fail-closed Omitting `faces` closes every surface. Omitting `readRole` means the collection is not anonymous. Neither defaults to open, so a collection cannot reach an agent by accident. `faces.mcp` takes the verbs to expose. `[search, list, get]` maps to `search_content`, `list_content`, and `get_content` for that collection. ## Different collections can reach different surfaces Faces are chosen per collection, so one blocklet can publish a collection to the web while keeping it off the agent surfaces entirely. A worked example from a site with five collections: | Collection | `web` | `sitemap` | `llms` | `mcp` | |---|---|---|---|---| | `docs`, `glossary`, `products` | Yes | Yes | Yes | Yes | | `articles` | Yes | Yes | **No** | Yes | | `events` | Yes | Yes | **No** | **No** | The reasoning behind that split is a judgement about what is worth an agent's tokens, not a technical limit: reference material earns a place in the text surfaces, a large archive of posts does not, and a list of past events serves neither. ## The declaration is observable You do not need the manifest to see the result. Two checks from outside: The collection list appears in each content tool's description and in its `collection` parameter, so `tools/list` shows exactly which collections have an `mcp` face: ```text Search published content by free text and optional facets. Collections: articles; docs; glossary; products ``` A collection with no `mcp` face is absent from that list; in the example above, `events`. The `llms` face is visible the same way. A collection with the face has a shard; one without it returns `404`: ```bash curl -s -o /dev/null -w '%{http_code}\n' https:///llms-docs.txt # 200 curl -s -o /dev/null -w '%{http_code}\n' https:///llms-articles.txt # 404 ``` ## Anonymous reads `readRole: guest` is what lets a caller without a credential read the collection through the content tools. Without it the tools still register, but that collection is not available to an anonymous caller. The tool names themselves are on the anonymous allowlist either way; see [Tools](../tools/#content-tools). --- ## Credentials without a browser URL: https://www.arcblock.io/en/docs/agent-access/device-grant/ The authorization code grant needs a browser to redirect to and a local port to redirect back to. A client with neither, such as a CLI on a server, a CI job, or an agent on a headless machine, uses the device grant instead. It produces the same credential as the browser grant: a `blocklet-` prefixed **access key**, sent as a bearer token. Replace `` with the blocklet's host. ## 1. Start a device authorization ```bash curl -s -X POST https:///.well-known/service/oauth/device_authorization \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'client_id=&scope=mcp' ``` ```json { "device_code": "bc0cedc2-899f-49da-b413-213f31c4aae8", "user_code": "BZVR-ZQZQ", "verification_uri": "https:///.well-known/service/gen-access-key", "verification_uri_complete": "https:///.well-known/service/gen-access-key?__token__=bc0cedc2-…", "expires_in": 300, "interval": 5 } ``` Obtain the `client_id` by registering first. See [Authorize a client](../authorize-a-client/#step-4-register-the-client). | Field | Use | |---|---| | `user_code` | Show it to the person. The alphabet excludes vowels and ambiguous characters, so it can be read aloud | | `verification_uri` | Where the person goes to approve | | `verification_uri_complete` | The same page with the request pre-filled; use it when you can render a link or a QR code | | `expires_in` | Seconds until **this request** expires. `300` above. It does not describe the credential | | `interval` | Minimum seconds between polls. `5` above | ## 2. The person approves Opening `verification_uri_complete` shows a consent screen naming the requesting application and the account, with an **access level** selector. It offers `owner` (the default), `admin`, `member`, and `guest`; the credential carries whichever is chosen. The role is scoped to this blocklet instance and is an upper bound, not a grant. See [Access tiers](../access-tiers/#roles). ## 3. Poll for the credential Poll the token endpoint with the device code grant until the request is approved or expires. Respect `interval`; polling faster is what the field exists to prevent. ```bash curl -s -X POST https:///.well-known/service/oauth/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \ --data-urlencode 'device_code=bc0cedc2-899f-49da-b413-213f31c4aae8' \ --data-urlencode 'client_id=' ``` Once approved: ```json { "access_token": "blocklet-zEJYCdC9awCqxEPLhqreFbwXjqU6Y2BHvKVQAx6kMZfRh", "token_type": "Bearer", "scope": "mcp" } ``` Before approval, and after the five-minute window closes, the same request answers `400`: ```json {"error":"invalid_grant","error_description":"Invalid or expired device_code"} ``` `invalid_grant` most often means the window expired rather than that the code was wrong. Restart from step 1. **No `expires_in`, no `refresh_token`.** The authorization server advertises `refresh_token` as a supported grant, but this flow does not return one. Treat the access key as the credential you keep. ## 4. Use it ```bash curl -s -X POST https:///mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -H 'Authorization: Bearer blocklet-…' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' ``` The credential clears the credential gate. It does not clear the path policy: an authenticated write can still return `AFS_FORBIDDEN`. See [Authorize a client](../authorize-a-client/#what-the-credential-leaves-closed). ## Which grant to use | Situation | Grant | |---|---| | Client can open a browser and listen on a local port | `authorization_code` with PKCE. See [Authorize a client](../authorize-a-client/) | | Client has no browser, or the person approving is on a different device | Device grant, this page | MCP clients generally implement the authorization code grant, not the device grant. Use the device grant for your own tooling rather than expecting a third-party MCP client to discover and drive it. --- ## Discovery surfaces URL: https://www.arcblock.io/en/docs/agent-access/discovery-surfaces/ A blocklet publishes four discovery **documents**. All are anonymous `GET` requests and none requires a prior connection to `/mcp`. Replace `` with the blocklet's host. The server card is reachable at three paths that return the same document, so [Endpoints](../endpoints/) lists more rows than there are documents. The authorization endpoints listed there are a different surface: they are named *by* these documents, not among them. | Path | Answers | |---|---| | `/.well-known/mcp.json` | What this MCP server is, where it is, and which tools need a credential | | `/.well-known/oauth-protected-resource` | Which authorization server protects `/mcp` | | `/.well-known/oauth-authorization-server` | Endpoints, grant types, PKCE method | | `/.well-known/api-catalog` | Which service descriptions exist on this host | ## Server card ```bash curl -s https:///.well-known/mcp.json ``` ```json { "name": "arc", "description": "AFS MCP server — agents discover published content via content tools and generic afs_* tools. Anonymous public read; authenticated writes via DID-Connect.", "url": "https:///mcp", "transport": "streamable-http", "authentication": { "required": false, "schemes": ["bearer"], "oauth_protected_resource": "https:///.well-known/oauth-protected-resource", "note": "Anonymous callers may tools/list and generic public-read afs_* tools; content tools (when declared without readRole:guest) and write/delete/exec require DID-Connect session." }, "tools": { "anonymous": ["afs_read", "afs_list", "afs_search", "afs_stat", "afs_explain"], "authenticated": ["afs_write", "afs_delete", "afs_exec"] } } ``` `authentication.required` is `false` because connecting and reading do not require a credential. The `tools` object states which names change that. The example above is from a blocklet that declares no content collections. One that declares them lists `search_content`, `list_content`, and `get_content` under `tools.anonymous` as well. The server card is not part of the MCP protocol, so MCP clients do not read it during a connection. Use it when you want to inspect a host, build a directory, or decide whether to connect at all, not as the mechanism that triggers authorization. That mechanism is the `401` challenge described in [Authorize a client](../authorize-a-client/). ## Protected resource ```bash curl -s https:///.well-known/oauth-protected-resource ``` ```json { "resource": "https:///mcp", "authorization_servers": ["https://"] } ``` This is the document the `WWW-Authenticate` challenge points at. It always names the same host as its own authorization server. ## Authorization server metadata Endpoints and grant types are listed in [Authorize a client](../authorize-a-client/#step-3-authorization-server-metadata). The document is served from the blocklet host, but the endpoints it names are implemented by the connect service; see [Endpoints](../endpoints/). ## API catalog ```bash curl -s https:///.well-known/api-catalog ``` ```json { "linkset": [ { "anchor": "https:///mcp", "https://www.iana.org/assignments/link-relations/link-relations.xhtml#service-desc": [ { "href": "https:///.well-known/mcp.json" } ] }, { "anchor": "https:///api/afs/rpc", "https://www.iana.org/assignments/link-relations/link-relations.xhtml#service-desc": [ { "href": "https:///.well-known/mcp.json" } ] } ] } ``` Two anchors are listed: the MCP endpoint, and the AFS RPC endpoint for clients that do not speak MCP. Both point at the same service description. ## Known drift The server card's `authentication.note` names a DID-Connect session as the way to authenticate writes. A bearer token obtained through the authorization server is also accepted, and the `schemes` field already says `bearer`. Treat `schemes` and the [access tiers](../access-tiers/) as authoritative and the prose note as incomplete. --- ## Endpoints URL: https://www.arcblock.io/en/docs/agent-access/endpoints/ All paths below are relative to a blocklet host. Replace `` with that host. ## Data plane | Path | Method | Credential | Notes | |---|---|---|---| | `/mcp` | `POST` | Optional | MCP over streamable HTTP. Stateless: no `mcp-session-id` is issued, and `initialize` is not required before other methods | | `/api/afs/rpc` | `POST` | Optional | AFS operations for clients that do not speak MCP | Anonymous requests to `/mcp` may use the handshake methods, the list methods, and the read tools. Anything else returns `401` with a `WWW-Authenticate` header naming the protected-resource document. ## Discovery All four are `GET` and none requires a credential. | Path | Serves | |---|---| | `/.well-known/mcp.json` | Server card: name, URL, transport, authentication summary, tool split | | `/.well-known/mcp` | Same document | | `/.well-known/mcp/server-card.json` | Same document | | `/.well-known/oauth-protected-resource` | RFC 9728 protected-resource metadata | | `/.well-known/oauth-authorization-server` | RFC 8414 authorization server metadata | | `/.well-known/api-catalog` | RFC 9727 linkset naming the service descriptions on this host | The three server-card paths are aliases for one document. Use whichever your client already looks for. ## Authorization These paths are named by the authorization server metadata and served by the connect service running behind the same host. To an agent they are ordinary paths on the blocklet host. | Path | Method | Credential | Purpose | |---|---|---|---| | `/.well-known/service/oauth/register` | `POST` | None | Dynamic client registration. Returns a `client_id` and echoes the registration | | `/.well-known/service/oauth/authorize` | `GET`, `POST` | User session | Authorization request and consent | | `/.well-known/service/oauth/token` | `POST` | PKCE verifier | Token exchange and refresh | | `/.well-known/service/oauth/device_authorization` | `POST` | None | Device flow, for clients that cannot open a browser | | `/.well-known/service/gen-access-key` | `GET` | User session | Browser page that completes an authorization in a user's session | Grant types advertised: `authorization_code`, `refresh_token`, and the device code grant. PKCE method: `S256`. Token endpoint authentication: `none`. ## Response shapes | Request | Result | |---|---| | `POST /mcp` `tools/list`, anonymous, no `initialize` | `200`; eight tools, or eleven when the blocklet declares content collections | | `POST /mcp` `tools/call afs_write`, anonymous | `401`, body `{"error":"Unauthorized"}`, header `www-authenticate: Bearer resource_metadata="https:///.well-known/oauth-protected-resource"` | | `GET /.well-known/oauth-protected-resource` | `200`; `resource` is `https:///mcp`, `authorization_servers` is `["https://"]` | | `GET /.well-known/oauth-authorization-server` | `200`; `issuer` equals the host | | `POST /.well-known/service/oauth/register` | `201`; `client_id` plus the echoed registration fields | | `POST /.well-known/service/oauth/device_authorization` | `200`; `device_code`, `user_code`, `verification_uri`, `verification_uri_complete`, `expires_in: 300`, `interval: 5` | | `POST /.well-known/service/oauth/token` (device grant, approved) | `200`; `{"access_token":"blocklet-…","token_type":"Bearer","scope":"mcp"}`, with no `expires_in` and no `refresh_token` | | `POST /mcp` `tools/call afs_write`, owner credential, undeclared path | `200` with `isError` and `AFS_FORBIDDEN` | For every failure shape and how to tell them apart, see [Errors](../errors/). ## Text surfaces | Path | Method | Credential | Serves | |---|---|---|---| | `/llms.txt` | `GET` | None | Pointer document naming the agent surfaces, plus a section per collection | | `/llms-.txt` | `GET` | None | Index for one collection. `404` when the collection declared no `llms` face | | `/llms--full.txt` | `GET` | None | Full text for one collection | | `/llms-full.txt` | `GET` | None | Full text for every collection | See [llms.txt](../llms-txt/). ## Compatibility path | Path | Notes | |---|---| | `arc mcp` | Bridges stdio to a running local daemon, for clients that cannot use HTTP. See [`arc mcp`](../../arc-cli/command-reference-mcp/) | --- ## Errors URL: https://www.arcblock.io/en/docs/agent-access/errors/ Failures arrive in two shapes, and confusing them wastes time. | Shape | Meaning | Where it is decided | |---|---|---| | HTTP `4xx` with no JSON-RPC result | The call never reached a tool | Method allowlist or credential, [gates 1 and 2](../access-tiers/) | | HTTP `200` with `"isError": true` | The call reached the tool; the operation failed | Path policy or provider, [gates 3 and 4](../access-tiers/) | A `200` is not success. Check `result.isError` on every `tools/call`. ## Transport failures ### `401` on `/mcp` ```http HTTP/1.1 401 Unauthorized www-authenticate: Bearer resource_metadata="https:///.well-known/oauth-protected-resource" {"error":"Unauthorized"} ``` The body is identical for every cause. Three produce it: | Cause | How to tell | Fix | |---|---|---| | Anonymous call to a write tool | You sent no `Authorization` header | Follow the challenge: [Authorize a client](../authorize-a-client/) | | Method not on the anonymous allowlist | The method is not `initialize` / `tools/list` / `resources/list` / `prompts/list` / an allowed `tools/call` | Authenticate, or use an allowed method | | Credential rejected | You sent a header but it is malformed, unknown, or issued by a different blocklet | Obtain a credential from **this** host. Credentials are instance-bound | An unknown tool name also returns `401` when you are anonymous, not a "no such tool" error. The allowlist is checked before the tool is looked up. If a tool name you saw in `tools/list` returns `401`, it is a privileged tool, not a typo. ## Authorization-flow failures All are `400` with an RFC 6749 error code. | Request | Response | |---|---| | `POST /oauth/register` without `redirect_uris` | `{"error":"invalid_redirect_uri","error_description":"Missing redirect_uris"}` | | `POST /oauth/register` with an unsupported scheme | `{"error":"invalid_redirect_uri","error_description":"redirect_uris must be https, RFC 8252 loopback http, or a private-use scheme …"}` | | `POST /oauth/token` with an unknown or expired `device_code` | `{"error":"invalid_grant","error_description":"Invalid or expired device_code"}` | | `POST /oauth/token` with any other grant | `{"error":"unsupported_grant_type","error_description":"Only device_code, authorization_code, and refresh_token grants are supported"}` | Two more you should expect but that are not shown above: - **Registration is rate limited per source address.** A client that re-registers on every start will eventually be throttled. Register once and keep the `client_id`. - **A registration that is never used in a completed authorization is swept after seven days.** A long-lived client that registered but never got consent must register again. `invalid_grant` on a device code most often means the five-minute window expired, not that the code was wrong. Restart the flow. ## In-call failures These arrive as `200` with `isError`. The text is a code followed by the path and an explanation. ### `AFS_FORBIDDEN` ```text AFS_FORBIDDEN: Forbidden at /instance/notes.txt: network clients cannot write base paths; use a resolver overlay or internal code ``` The blocklet has not opened that path to network clients. Variants: | Operation | Text | |---|---| | write | `cannot write base paths; use a resolver overlay or internal code` | | read | `cannot read base paths; declare a networkRead rule or use an overlay` | | list | `cannot list base paths; declare a networkRead rule or use an overlay` | | stat | `cannot stat base paths; declare a networkRead rule or use an overlay` | **A credential does not fix this.** An owner-role caller gets the same refusal. Only the blocklet's own declaration changes it. See [Access tiers, gate 3](../access-tiers/#gate-3-the-path-policy). ### `AFS_NOT_FOUND` ```text AFS_NOT_FOUND: Path not found: /new ``` The path does not exist **on this host**. Paths are host-scoped, so a path that resolves on one blocklet can be absent on another even when both mount the same provider name. Confirm with `afs_list` on the parent before assuming the provider is missing. ## Diagnosing in order Work down the gates; each step rules out everything above it. 1. **Does anonymous `tools/list` return `200`?** No → the host is not reachable or is not an ARC blocklet. Check the URL and `/.well-known/mcp.json`. 2. **Does the tool appear in `tools/list`?** No → for content tools, the blocklet declared no collections; see [Declare what agents see](../declare-what-agents-see/). 3. **Does calling it return `401`?** Yes → gate 1 or 2. Follow the `WWW-Authenticate` challenge. 4. **Does it return `200` with `AFS_FORBIDDEN`?** Yes → gate 3. The credential is fine; the path is closed to the network. 5. **Does `afs_stat` show the operation in `capabilities`?** No → gate 4. The provider does not implement it. ## Refreshing a credential The device grant returns a credential with no expiry and no refresh token, so there is nothing to refresh. If a credential stops working, sign in again with your tool, see [Connect your tool](../clients/). --- ## llms.txt URL: https://www.arcblock.io/en/docs/agent-access/llms-txt/ `/llms.txt` is a pointer. It names the endpoints, tools, and collections an agent can use on this host, and links to per-collection index shards. It is not a copy of the site. An agent that fetches it learns where to connect in roughly a kilobyte, instead of reading the site as text. ## Fetch it ```bash curl -s https:///llms.txt ``` ```text # ArcBlock > ArcBlock builds decentralized identity, user-owned data, Blocklet > infrastructure, and AI-native application systems. ## For agents - MCP (Streamable HTTP): https:///mcp - Server card: https:///.well-known/mcp.json - AFS over HTTP (JSON-RPC): POST https:///api/afs/rpc - Tools: search_content, list_content, get_content - Collections available to agents: articles, docs, glossary, products - Anonymous public read; writes require DID-Connect auth Locales: en, zh, ja, zh-TW (base: en). … Full-text version (all collections, never truncated): https:///llms-full.txt ## Docs (1268 items) Index: https:///llms-docs.txt Full text: https:///llms-docs-full.txt ``` The document above is 1,142 bytes. The `For agents` block is the part that matters: it hands over the MCP endpoint, the server card, and the JSON-RPC endpoint, so a client that can do better than reading text does not have to read text. ## Shards Each collection that declared an `llms` face gets an index shard and a full-text shard. | Path | Contains | |---|---| | `/llms.txt` | The pointer above, plus a section per collection with item counts and shard links | | `/llms-.txt` | Index for one collection | | `/llms--full.txt` | Full text for one collection | | `/llms-full.txt` | Full text for every collection | A collection without the face has no shard: ```bash curl -s -o /dev/null -w '%{http_code} %{size_download}\n' https:///llms-docs.txt # 200 154869 curl -s -o /dev/null -w '%{http_code} %{size_download}\n' https:///llms-articles.txt # 404 9 ``` Which collections have the face is a per-blocklet decision; see [Declare what agents see](../declare-what-agents-see/). ## Sizes are not symmetric On a site with about 1,300 documents the pointer is around 1 KB, the docs index shard is around 150 KB, and `/llms-full.txt` is several megabytes. The shards exist so an agent can take the one collection it needs. `llms-full.txt` is there for completeness, not as the intended entry point. Fetching it costs more context than connecting over MCP and asking a question. ## When to use which | Situation | Use | |---|---| | The client speaks MCP | `/mcp`. Query instead of ingesting | | The client can issue HTTP but has no tool harness | [`/api/afs/rpc`](../afs-over-http/) | | The client can only fetch text | `/llms.txt`, then the one shard it needs | `llms.txt` names the first two, so an agent that starts at the text surface can move up to a better one. --- ## Agent access URL: https://www.arcblock.io/en/docs/agent-access/overview/ A blocklet running on ARC exposes an MCP endpoint at `/mcp` and a set of discovery documents under `/.well-known/`. The runtime provides them; a blocklet does not opt in and cannot be deployed without them. An agent that knows only the host URL can therefore reach the endpoint and list the available tools before any credential exists. What it can then *read* is decided by the blocklet, not by the runtime. ## Three ways to connect | Client can | Endpoint | |---|---| | Speak MCP | `POST /mcp`, streamable HTTP, stateless | | Issue HTTP but has no tool-calling harness | `POST /api/afs/rpc`, the same operations as JSON-RPC | | Only fetch text | `GET /llms.txt`, a pointer that names the other two | All three serve the same data. Prefer `/mcp` when your client supports it. ## Check the baseline first Anonymous `tools/list` must work on every blocklet: no credential, no `initialize`, no session. ```bash curl -s -X POST https:///mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' ``` It answers with at least the eight generic AFS tools. If this fails, the problem is the host or the transport, not access. → [Connect a client](../connect-a-client/) ## Something already failed? | What you got | What it means | Where | |---|---|---| | `401` with `WWW-Authenticate` | The method is not anonymous-safe, or your credential was rejected | [Errors](../errors/) · [Authorize a client](../authorize-a-client/) | | `200` with `"isError": true` and `AFS_FORBIDDEN` | The call reached the tool. The blocklet has not opened that path to network clients | [Access tiers](../access-tiers/) | | Writes still refused with an owner credential | Expected. A credential is not a write switch | [Access tiers](../access-tiers/) | | `tools/list` returns only the eight AFS tools | The blocklet declares no content collections | [Tools](../tools/) | | Not sure you have the right host | `GET /.well-known/mcp.json` and check its `url` field | [Discovery surfaces](../discovery-surfaces/) | **A `200` is not success.** Check `result.isError` on every `tools/call`. ## What decides whether a call succeeds Four independent gates, decided by three different parties: the runtime, the blocklet, and the provider. A credential is an answer to the runtime, so it clears one gate and leaves the other three exactly where they were. Gate 3 — what the blocklet declared for that path — is the one most agents hit, and no credential bypasses it, including an owner-role credential. → [Access tiers](../access-tiers/) for all four gates and why they are separate ## Publishing a tool is not the same as allowing it Anonymous `tools/list` publishes the write tools alongside the read tools. Calling one without a credential returns `401` with a challenge. This is deliberate. A well-behaved MCP client only calls tools that were advertised to it, so hiding the write tools would mean the client never issues the request that produces the challenge. A challenge is what starts a standard authorization flow. Publishing the tools is what makes authorization discoverable. ## Each blocklet issues its own credentials The protected-resource document on a host names that same host as its authorization server. A credential obtained from one blocklet does not open another; it carries the instance it was issued for, and the runtime compares that instance on every call. There is no cross-blocklet credential. ## Where this board sits [AFS](../../afs/) defines the paths, providers, and capability contract. This board is about **reaching that contract from outside**: which protocol surfaces exist on a host, how a client authenticates to them, and what a blocklet has to declare before an external caller sees anything. If your question is "what does `afs_read` guarantee", read AFS. If it is "how does my agent get to call it", read on here. ## Where to go next | | | |---|---| | **Connect** | [Connect a client](../connect-a-client/) · [Claude Code and Codex CLI](../clients/) | | **Authenticate** | [Authorize a client](../authorize-a-client/) · [without a browser](../device-grant/) | | **Look something up** | [Errors](../errors/) · [Endpoints](../endpoints/) · [Understand the model](../understand/) | --- ## Tools URL: https://www.arcblock.io/en/docs/agent-access/tools/ A blocklet publishes two kinds of MCP tools. The generic AFS tools are always registered. The content tools are registered only when the blocklet declares content collections, and their input schemas name the collections it declared. Both kinds run over the same data plane. The content tools are wrappers over AFS search, list, and read. There is no second store behind them. ## Generic AFS tools | Tool | Required | Other parameters | Anonymous | |---|---|---|---| | `afs_read` | none | `path`, `entries`, `startLine`, `endLine` | Yes | | `afs_list` | `path` | `depth`, `pattern`, `limit` | Yes | | `afs_search` | `path`, `query` | `pattern`, `limit`, `explain` | Yes | | `afs_stat` | `path` | none | Yes | | `afs_explain` | `path` | none | Yes | | `afs_write` | none | `path`, `content`, `mode`, `patches`, `ifMatch`, `entries` | No | | `afs_delete` | none | `path`, `recursive`, `ifMatch`, `entries` | No | | `afs_exec` | `path` | `args` | No | `afs_read`, `afs_write`, and `afs_delete` show no required field because they accept **either** a single `path` **or** an `entries` array; one of the two is mandatory. Batch the array rather than looping single calls; `afs_read` accepts up to 16 entries per call. `afs_exec` runs a declared action. Discover the available actions and their input schemas by listing `{path}/.actions`. For what these paths and operations mean, and which operations a given provider actually implements, see [AFS](../../afs/). A tool being listed and callable does not mean it will succeed on a given path: the blocklet's path policy is checked inside the call. See [Access tiers](../access-tiers/#gate-3-the-path-policy). ## Content tools | Tool | Required | Other parameters | |---|---|---| | `search_content` | `collection`, `query` | `filters`, `locale`, `limit` | | `list_content` | `collection` | `filters`, `locale`, `limit` | | `get_content` | `collection`, `id` | `locale` | These three appear only when the blocklet declares collections. A blocklet with no declaration registers none of them. The gate is fail-closed, so a partial or empty declaration does not produce a tool with an empty collection list. The declared collection names are written into each tool's description and into the `collection` parameter, so a client sees them in `tools/list` without probing. A blocklet that declares four collections produces descriptions ending in a list of those four names. Whether they are callable anonymously depends on the read role the blocklet declared for the collection. The tool names themselves are on the anonymous allowlist; the collections visible inside them are decided at registration time. ## Which set a host returns `tools/list` returns eight tools from a blocklet with no declared collections, and eleven from a blocklet that declares them. The difference is the blocklet's own declaration, not the caller's credential: an anonymous client and an authenticated client see the same list. What changes with a credential is which of those tools answer. See [Connect a client](../connect-a-client/#what-anonymous-access-gives-you). ## Declaring collections The declaration lives in the blocklet's own manifest, alongside the rest of its capabilities. That surface is documented with the manifest, not here; see [Blocklets](../../blocklets/). --- ## Understand agent access URL: https://www.arcblock.io/en/docs/agent-access/understand/ [Connect a client](../connect-a-client/) and [Authorize a client](../authorize-a-client/) are enough to get an agent talking to a blocklet. This section explains why the results look the way they do, so you can predict them instead of probing. Three questions organise it. ## What decides whether a call succeeds Four independent gates: the method allowlist, the credential, the path policy, and the provider's capabilities. Most surprises come from assuming a credential clears all four. It clears one. → [Access tiers](../access-tiers/) ## What a blocklet chooses to expose An ARC blocklet does not expose its data because it is running; it exposes what its manifest declares. The same declaration drives the MCP content tools, the `llms` shards, the sitemap, and the web pages. Two blocklets on the same runtime can answer very differently. → [Tools](../tools/) for what is callable · [Declare what agents see](../declare-what-agents-see/) for what drives it ## Which surface to use There are three ways in, meant for clients of different capability. They serve the same data. | Client can | Use | Page | |---|---|---| | Speak MCP | `/mcp` | [Discovery surfaces](../discovery-surfaces/) for how to find it | | Issue HTTP, but has no tool-calling harness | `/api/afs/rpc` | [AFS over HTTP](../afs-over-http/) | | Only fetch text | `/llms.txt` and its shards | [llms.txt](../llms-txt/) | The text surface names the other two, so an agent that starts there can move up to a better one. ## Reading order If you are new to this board, read [Access tiers](../access-tiers/) first, because every other page in this section refers to its four gates. The rest can be read in any order. --- ## agent-access/visuals URL: https://www.arcblock.io/en/docs/agent-access/visuals/ --- ## AIGNE CLI URL: https://www.arcblock.io/en/docs/aigne-cli/ --- ## Built-in Apps URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-built-in-apps-cdbd13/ AIGNE CLI comes with pre-packaged applications that offer specialized, out-of-the-box functionality. These apps are complete AIGNE projects that you can execute directly, without needing to initialize a local project first. When you invoke a built-in app for the first time, the CLI automatically fetches its package from the npm registry, installs it into a local cache (`~/.aigne/`), and then runs it. Subsequent runs use the cached version for faster startup, with periodic checks for new updates to ensure you have the latest features. ## Available Apps Here are the currently available built-in applications: | Command | Aliases | Description | |---|---|---| | `doc` | `docsmith` | Generate and maintain project docs — powered by agents. | | `web` | `websmith` | Generate and maintain project website pages — powered by agents. | ## Doc Smith (aigne doc) Doc Smith is a powerful application designed to automate the generation and maintenance of project documentation using AI agents. ### Usage You can interact with Doc Smith using the `aigne doc` command. The agents defined within the Doc Smith application are available as subcommands. For example, to generate documentation for your current project, you would run its `generate` agent: **Generate project documentation** ```bash # Run the 'generate' agent to create or update docs aigne doc generate ``` ## Web Smith (aigne web) Web Smith is an application focused on generating and maintaining web pages for your project, such as landing pages, feature showcases, or blogs. ### Usage Similar to Doc Smith, you use the `aigne web` command followed by the name of an agent within the Web Smith application. For example, to generate a new web page: **Generate a new web page** ```bash # Run an agent to create a new page aigne web generate ``` ## Common Commands Since built-in apps are full AIGNE projects, they support standard commands that you can apply to them directly. ### Upgrade To ensure you have the latest version of an application, you can run the `upgrade` command. This will check for a newer version on npm and install it if available. **Upgrade Doc Smith** ```bash aigne doc upgrade ``` ### Serve as MCP Server You can expose an application's agents as a standard Model Context Protocol (MCP) service, allowing other systems to interact with them over HTTP. **Serve Doc Smith agents** ```bash aigne doc serve-mcp ``` For a full list of server options, see the [`aigne serve-mcp`](/en/docs/aigne-cli/command-reference-serve-mcp-cdbd13/) command reference. --- ## Command Reference URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-cdbd13/ The AIGNE Command-Line Interface (CLI) is your primary tool for creating, managing, and deploying AIGNE agents. This section serves as a comprehensive reference for all available commands and their options, organized for quick look-up. For a more guided experience, check out our [Getting Started](/en/docs/aigne-cli/getting-started-cdbd13/) guide or the practical examples in the [Guides](/en/docs/aigne-cli/guides-cdbd13/) section. ::::card-group ::link-card{title="aigne create" description="Scaffolds a new AIGNE project from a template." icon="folder-plus" href="/en/docs/aigne-cli/command-reference-create-cdbd13/"} ::link-card{title="aigne run" description="Executes an agent locally or from a remote URL, with options for chat mode, model selection, and input handling." icon="play" href="/en/docs/aigne-cli/command-reference-run-cdbd13/"} ::link-card{title="aigne serve-mcp" description="Serves agents as a Model Context Protocol (MCP) server for integration with external systems." icon="server" href="/en/docs/aigne-cli/command-reference-serve-mcp-cdbd13/"} ::link-card{title="aigne hub" description="Manages connections to the AIGNE Hub, allowing you to switch accounts, check status, and use Hub-provided models." icon="cloud" href="/en/docs/aigne-cli/command-reference-hub-cdbd13/"} ::link-card{title="aigne observe" description="Starts a local server to view and analyze agent execution traces and observability data." icon="eye" href="/en/docs/aigne-cli/command-reference-observe-cdbd13/"} ::link-card{title="aigne test" description="Runs automated tests for your agents and skills." icon="activity" href="/en/docs/aigne-cli/command-reference-test-cdbd13/"} ::link-card{title="aigne deploy" description="Deploys an AIGNE application as a Blocklet to a specified endpoint." icon="rocket" href="/en/docs/aigne-cli/command-reference-deploy-cdbd13/"} ::link-card{title="Built-in Apps" description="Execute pre-packaged applications like `doc-smith` for specialized, out-of-the-box agent functionality." icon="box" href="/en/docs/aigne-cli/command-reference-built-in-apps-cdbd13/"} :::: --- ## aigne create URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-create-cdbd13/ The `aigne create` command scaffolds a new AIGNE project from a template. It sets up the necessary directory structure and configuration files, allowing you to start developing your agent immediately. ## Usage **Basic Usage** ```bash aigne create [path] ``` ## Arguments - **path** `string` (default: `.`) — The path where the new project directory will be created. If omitted, it defaults to the current directory and triggers an interactive mode to prompt for the project name. ## Interactive Mode If you run `aigne create` without specifying a path, or by using `.` for the current directory, the CLI enters an interactive mode to guide you through the setup process. You will be prompted for the following information: - Project name: The name for your new project directory. - Template: The project template to use. Currently, only a `default` template is available. ![Interactive prompt for project name](https://media.arcblock.io/lib/06/06e97c00fd2a53ff.w1600.webp) ### Overwrite Confirmation For safety, if the target directory already exists and is not empty, the CLI will ask for your confirmation before proceeding to remove its contents. If you choose not to proceed, the operation will be safely cancelled. **Confirmation Prompt** ```text ? The directory "/path/to/my-aigne-project" is not empty. Do you want to remove its contents? (y/N) ``` ## Examples ### Create a Project Interactively To be guided through the creation process, run the command without any arguments. The CLI will prompt you for a project name. **Create in the current directory** ```bash aigne create ``` ### Create a Project in a Specific Directory To create a project in a new directory named `my-awesome-agent`, provide the name as an argument. **Create in a new 'my-awesome-agent' directory** ```bash aigne create my-awesome-agent ``` This command creates the `my-awesome-agent` directory and scaffolds the project inside it. You will still be prompted to select a template. ## Successful Output Upon successful creation, you will see a confirmation message and instructions for the next steps to run your new agent. ![Project creation success message](https://media.arcblock.io/lib/da/dacdbcdeba96a78e.w1600.webp) After creating your project, the next step is to execute your agent. For more details, see the [`aigne run`](/en/docs/aigne-cli/command-reference-run-cdbd13/) command reference. --- ## aigne deploy URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-deploy-cdbd13/ The `aigne deploy` command packages and deploys your AIGNE application as a [Blocklet](https://www.blocklet.dev/) to a specified Blocklet Server endpoint. This is the standard way to publish your agent for production use, making it accessible as a self-contained, executable service. ## Usage **Basic Usage** ```bash aigne deploy --path --endpoint ``` ## Options - **--path** `string` *(required)* — Specifies the path to the AIGNE project directory that contains the aigne.yaml file. - **--endpoint** `string` *(required)* — The URL of the Blocklet Server endpoint where the application will be deployed. ## Deployment Process The `deploy` command automates several steps to package your agent correctly and deploy it to the target environment. The process is interactive on the first run for a given project and non-interactive for subsequent updates. **Deployment Workflow** ```d2 direction: down Developer: { shape: c4-person } CLI: { label: "`aigne deploy`" task-1: { label: "1. Prepare Environment" } task-2: { label: "2. Check Blocklet CLI" } task-3: { label: "3. Configure Blocklet\n(Name & DID)" } task-4: { label: "4. Bundle Project" } task-5: { label: "5. Deploy to Server" } task-1 -> task-2 -> task-3 -> task-4 -> task-5 } Blocklet-Server: { label: "Blocklet Server" icon: "https://www.arcblock.io/image-bin/uploads/eb1cf5d60cd85c42362920c49e3768cb.svg" } Deployed-Blocklet: { label: "Deployed Agent\n(as Blocklet)" } Developer -> CLI: "Run command with path & endpoint" CLI.task-5 -> Blocklet-Server: "Upload bundle" Blocklet-Server -> Deployed-Blocklet: "Host agent" ``` Here is a step-by-step breakdown of what happens when you run the command: 1. Environment Preparation: A temporary `.deploy` directory is created in your project root. The command copies your agent's source files and a standard Blocklet template into this directory to prepare for packaging. 2. Dependency Installation: If a `package.json` file is present, it runs `npm install` within the temporary directory to fetch all necessary dependencies. 3. Blocklet CLI Check: The command verifies that the `@blocklet/cli` is installed globally. If it's missing, you will be prompted to install it automatically, as it is required for packaging and deploying Blocklets. 4. Configuration (First-Time Deploy): On the first deployment of a project, the CLI will guide you through a brief interactive setup: 5. - Blocklet Name: You will be asked to provide a name for your Blocklet. It suggests a default based on the `name` field in your `aigne.yaml` or the project's directory name. - DID Generation: A new Decentralized Identifier (DID) is automatically generated for your Blocklet using `blocklet create --did-only`, giving it a unique, verifiable identity. - This configuration (name and DID) is saved locally in `~/.aigne/deployed.yaml`. For subsequent deployments of the same project, these saved values are used automatically, making the process non-interactive. 6. Bundling: The CLI executes `blocklet bundle --create-release` to package all your application files into a single, deployable artifact. 7. Deployment: The final bundle is uploaded to the `--endpoint` you specified using `blocklet deploy`. 8. Cleanup: After a successful deployment, the temporary `.deploy` directory is automatically removed. ## Example To deploy an AIGNE project located in the current directory to your Blocklet Server: **Deploying a project** ```bash aigne deploy --path . --endpoint https://my-node.abtnode.com ``` If this is the first time you are deploying this project, you will see a prompt to name your agent Blocklet: **First-time deployment prompt** ```text ✔ Prepare deploy environment ✔ Check Blocklet CLI ℹ Configure Blocklet ? Please input agent blocklet name: › my-awesome-agent ✔ Bundle Blocklet ... ✅ Deploy completed: /path/to/your/project -> https://my-node.abtnode.com ``` For a more detailed walkthrough on setting up a deployment target and managing your deployed agents, refer to the [Deploying Agents](/en/docs/aigne-cli/guides-deploying-agents-cdbd13/) guide. --- ## aigne hub URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-hub-cdbd13/ The `aigne hub` command is your central tool for managing connections to the AIGNE Hub. The Hub provides access to managed large language models, handles API key management, and tracks your credit usage. Properly configuring your Hub connection is essential for running agents that utilize Hub-provided models. This command set allows you to connect to new Hubs (both the official Arcblock Hub and self-hosted instances), list your existing connections, switch between them, and monitor your account status. ## Usage **Basic Command Structure** ```bash aigne hub ``` ## Commands The `aigne hub` command includes several subcommands to manage different aspects of your Hub connections. | Command | Alias | Description | |---|---|---| | `connect [url]` | | Connect to a new AIGNE Hub. | | `list` | `ls` | List all configured AIGNE Hub connections. | | `use` | | Switch the active AIGNE Hub. | | `status` | `st` | Display the currently active AIGNE Hub. | | `remove` | `rm` | Remove a configured AIGNE Hub connection. | | `info` | `i` | Show detailed information for a specific Hub connection. | ### connect [url] Connects your local CLI to an AIGNE Hub instance. This process authenticates your machine and stores an API key for future requests in the `~/.aigne/aigne-hub-connected.yaml` file. Usage **Connect to a Hub** ```bash aigne hub connect [url] ``` Behavior - Interactive Mode: If you run the command without a URL, an interactive prompt will appear, allowing you to choose between the official AIGNE Hub or a custom, self-hosted Hub URL. **Interactive Connection** ```bash $ aigne hub connect ? Choose a hub to connect: › - Use arrow-keys. Return to submit. ❯ Official Hub (https://hub.aigne.io) Custom Hub URL ``` - Direct Mode: If you provide a URL, the CLI will attempt to connect to that specific Hub directly. **Direct Connection** ```bash $ aigne hub connect https://my-hub.example.com ``` In both cases, a browser window will open for you to authenticate and authorize the CLI connection. Once completed, the credentials will be saved locally. ### list Displays a table of all AIGNE Hubs you have previously connected to. It also indicates which Hub is currently active. Usage **List Connections** ```bash aigne hub list # or using the alias aigne hub ls ``` Example Output ```bash $ aigne hub ls Connected AIGNE Hubs: ┌───────────────────────────────────────────────────┬────────┐ │ URL │ ACTIVE │ ├───────────────────────────────────────────────────┼────────┤ │ https://hub.aigne.io │ YES │ ├───────────────────────────────────────────────────┼────────┤ │ https://my-hub.example.com │ NO │ └───────────────────────────────────────────────────┴────────┘ Use 'aigne hub use' to switch to a different hub. ``` ### use Switches the active AIGNE Hub. This command is useful when you have multiple Hub connections (e.g., a personal account and a team account) and need to change which one is used by default for commands like `aigne run`. Usage **Switch Active Hub** ```bash aigne hub use ``` Behavior Running this command will present an interactive list of your saved Hub connections. Select the one you wish to make active. **Interactive Switch** ```bash $ aigne hub use ? Choose a hub to switch to: › - Use arrow-keys. Return to submit. https://hub.aigne.io ❯ https://my-hub.example.com ✓ Switched active hub to https://my-hub.example.com ``` ### status Quickly shows the URL of the currently active AIGNE Hub and its connection status. Usage **Check Status** ```bash aigne hub status # or using the alias aigne hub st ``` Example Output ```bash $ aigne hub status Active hub: https://hub.aigne.io - online ``` ### remove Removes a saved AIGNE Hub connection from your local configuration file. Usage **Remove a Hub** ```bash aigne hub remove # or using the alias aigne hub rm ``` Behavior This command will interactively prompt you to select which of your saved Hub connections you want to remove. **Interactive Removal** ```bash $ aigne hub remove ? Choose a hub to remove: › https://my-hub.example.com ✓ Hub https://my-hub.example.com removed ``` ### info Fetches and displays detailed account information for a selected Hub connection. This includes user details, credit balance, and important links. Usage **Get Hub Info** ```bash aigne hub info # or using the alias aigne hub i ``` Behavior First, you will be prompted to select a configured Hub. Then, the CLI will display its connection status and your account details. Example Output ```bash $ aigne hub info AIGNE Hub Connection ────────────────────────────────────────────── Hub: https://hub.aigne.io Status: Connected ✅ User: Name: John Doe DID: z2qa...w9vM Email: john.doe@example.com Credits: Used: 1,234 Total: 100,000 Links: Payment: https://hub.aigne.io/payment/... Profile: https://hub.aigne.io/profile/... ``` --- ## aigne observe URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-observe-cdbd13/ The `aigne observe` command launches a local web server for monitoring and analyzing agent execution data. It provides a user-friendly interface to inspect traces, view detailed call information, and understand your agents' behavior during runs. This tool is essential for debugging, performance tuning, and gaining deep insights into how your agents process information and interact with various tools and models. ## Usage To start the observability server, run the following command in your terminal: **Usage** ```bash aigne observe [options] ``` Upon starting, the CLI will print the server URL and the path to the local observability database. ![AIGNE observability server running interface](https://media.arcblock.io/lib/6c/6cd148bb88444bcb.w1600.webp) ## How It Works The `observe` command starts a web application that reads from a local SQLite database where AIGNE stores all execution traces. Each time you run an agent (using `aigne run` or `aigne serve-mcp`), the framework automatically records detailed logs of the execution flow. These logs then become available for inspection in the observability UI. The UI allows you to browse a list of all recorded traces and drill down into specific ones to see a step-by-step breakdown of the agent's operations, including inputs, outputs, tool calls, and model responses. ![Viewing call details in the AIGNE observability UI](https://media.arcblock.io/lib/eb/eb45cd17811ac2c5.w1600.webp) ## Options - **--host** `string` (default: `localhost`) — Specifies the host address for the server. Use `0.0.0.0` to expose the server to other devices on your local network. - **--port** `number` (default: `7890`) — Sets the port number for the server to listen on. If the specified port is unavailable, it will attempt to find the next available one. Can also be set via the `PORT` environment variable. ## Examples ### Start the server on the default port Running the command without any options starts the server with the default settings. **Start with default settings** ```bash aigne observe ``` Expected Output: **Console Output** ```text Observability database path: /path/to/your/project/.aigne/observability.db Observability server is running at http://localhost:7890 ``` You can then open `http://localhost:7890` in your web browser to access the UI. ### Start the server on a specific port Use the `--port` option to specify a different port. **Start on a custom port** ```bash aigne observe --port 8080 ``` This will start the server on `http://localhost:8080` (or the next available port if 8080 is in use). ### Expose the server to your local network To allow other devices on your network to access the observability UI, set the host to `0.0.0.0`. **Expose the server publicly** ```bash aigne observe --host 0.0.0.0 ``` The server will then be accessible via `http://:7890`. --- ## aigne run URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-run-cdbd13/ The `aigne run` command is the primary way to execute an AIGNE agent. It can run agents from a local project directory or directly from a remote URL. It offers a flexible set of options for providing input, configuring the AI model, and handling output, including an interactive chat mode for conversational agents. ## Usage **Basic Syntax** ```bash aigne run [path] [agent_name] [options] ``` ### Arguments - `[path]` (Optional): The path to the AIGNE project directory or a remote URL (e.g., a Git repository). If omitted, it defaults to the current directory (`.`). - `[agent_name]` (Optional): The specific agent to run from the project. If not specified, the CLI will use the `entry-agent` or the default `chat` agent defined in `aigne.yaml`, falling back to the first agent listed. ## How It Works The `run` command first loads the AIGNE application. If a remote URL is provided, it downloads and caches the project locally before proceeding. It then parses the command-line arguments and executes the specified agent with the given inputs and model configurations. **Remote Execution Flow** ```d2 direction: down User: { shape: c4-person } CLI: { label: "@aigne/cli" Download: { label: "Download Package" } Extract: { label: "Extract Package" } Load: { label: "Load Application" } Execute: { label: "Execute Agent" } } Remote-URL: { label: "Remote URL\n(e.g., GitHub)" shape: cylinder } Cache-Dir: { label: "Cache Directory\n(~/.aigne/.download)" shape: cylinder } Local-Dir: { label: "Local Directory\n(~/.aigne//...)" shape: cylinder } User -> CLI: "aigne run " CLI.Download -> Remote-URL: "1. Fetch project" Remote-URL -> CLI.Download: "2. Return tarball" CLI.Download -> Cache-Dir: "3. Save tarball" CLI.Extract -> Cache-Dir: "4. Read tarball" CLI.Extract -> Local-Dir: "5. Unpack project files" CLI.Load -> Local-Dir: "6. Load aigne.yaml & .env" CLI.Execute -> CLI.Load: "7. Run agent" CLI.Execute -> User: "8. Display output" ``` ## Examples ### Running a Local Agent Execute an agent from a project on your local filesystem. **Run from current directory** ```bash # Run the default agent in the current directory aigne run ``` **Run a specific agent** ```bash # Run the 'translator' agent located in a specific project path aigne run path/to/my-project translator ``` ### Running a Remote Agent You can run an agent directly from a Git repository or a tarball URL. The CLI handles downloading and caching the project in your home directory (`~/.aigne`). **Run from a GitHub repository** ```bash aigne run https://github.com/AIGNE-io/aigne-framework/tree/main/examples/default ``` ### Running in Interactive Chat Mode For conversational agents, use the `--interactive` flag to start an interactive terminal session. ![Running an agent in chat mode](https://media.arcblock.io/lib/72/7259ac6078e7393b.w1600.webp) **Start a chat session** ```bash aigne run --interactive ``` Inside the chat loop, you can use commands like `/exit` to quit and `/help` for assistance. You can also attach local files to your message by prefixing the path with `@`. ``` 💬 Tell me about this file: @/path/to/my-document.pdf ``` ## Providing Input to Agents There are multiple ways to provide input to your agents, depending on their defined input schema in `aigne.yaml`. #### As Command-Line Options If an agent's input schema defines specific parameters (e.g., `text`, `targetLanguage`), you can pass them as command-line options. **Pass agent-specific parameters** ```bash # Assuming 'translator' agent has 'text' and 'targetLanguage' inputs aigne run translator --text "Hello, world!" --targetLanguage "Spanish" ``` #### From Standard Input (stdin) You can pipe content directly to the `run` command. This is useful for chaining commands. **Pipe input to an agent** ```bash echo "Summarize this important update." | aigne run summarizer ``` #### From Files Use the `@` prefix to read content from a file and pass it as input. - `--input @`: Reads the entire file content as the primary input. - `-- @`: Reads file content for a specific agent parameter. **Read input from a file** ```bash # Use content of document.txt as the main input aigne run summarizer --input @document.txt # Provide structured JSON input for multiple parameters aigne run translator --input @request-data.json --format json ``` #### Multimedia File Inputs For agents that process files like images or documents (e.g., vision models), use the `--input-file` option. **Attach a file for a vision agent** ```bash aigne run image-describer --input-file cat.png --input "What is in this image?" ``` ## Options Reference ### General Options | Option | Description | |---|---| | `--interactive` | Run the agent in an interactive chat loop in the terminal. | | `--log-level ` | Set the logging level. Available levels: `debug`, `info`, `warn`, `error`, `silent`. Default: `silent`. | ### Model Options These options allow you to override the model configurations defined in `aigne.yaml`. | Option | Description | |---|---| | `--model ` | Specify the AI model to use (e.g., 'openai' or 'openai:gpt-4o-mini'). | | `--temperature ` | Model temperature (0.0-2.0). Higher values increase randomness. | | `--top-p ` | Model top-p / nucleus sampling (0.0-1.0). Controls response diversity. | | `--presence-penalty ` | Presence penalty (-2.0 to 2.0). Penalizes repeating tokens. | | `--frequency-penalty ` | Frequency penalty (-2.0 to 2.0). Penalizes frequent tokens. | | `--aigne-hub-url ` | Custom AIGNE Hub service URL for fetching remote models or agents. | ### Input & Output Options | Option | Alias | Description | |---|---|---| | `--input ` | `-i` | Input to the agent. Can be specified multiple times. Use `@` to read from a file. | | `--input-file ` | | Path to an input file for the agent (e.g., for vision models). Can be specified multiple times. | | `--format ` | | Input format when using `--input @`. Choices: `text`, `json`, `yaml`. | | `--output ` | `-o` | Path to a file to save the result. Defaults to printing to standard output. | | `--output-key ` | | The key in the agent's result object to save to the output file. Defaults to `output`. | | `--force` | | Overwrite the output file if it already exists. Creates parent directories if they don't exist. | ## Next Steps ::::card-group ::link-card{title="aigne observe" description="Learn how to start the observability server to view detailed traces of your agent runs." icon="monitor" href="/en/docs/aigne-cli/command-reference-observe-cdbd13/"} ::link-card{title="Running Remote Agents" description="Dive deeper into the specifics of executing agents directly from remote URLs." icon="cloud" href="/en/docs/aigne-cli/guides-running-remote-agents-cdbd13/"} ::link-card{title="Creating a Custom Agent" description="Get started with building your own agents and skills to use with the AIGNE CLI." icon="bot" href="/en/docs/aigne-cli/guides-creating-a-custom-agent-cdbd13/"} :::: --- ## aigne serve-mcp URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-serve-mcp-cdbd13/ Serves the agents in an AIGNE project as a Model Context Protocol (MCP) server. This command exposes your agents over a streamable HTTP endpoint, enabling seamless integration with external systems and applications that support the MCP standard. Internally, `aigne serve-mcp` starts a lightweight Express server. When a POST request is received on the configured endpoint, it invokes the corresponding agent and streams the response back according to the MCP specification. ![Running the MCP Service](https://media.arcblock.io/lib/c4/c48e4ceaa98674a8.w1600.webp) ## Usage **Basic Usage** ```bash aigne serve-mcp [options] ``` ## Options The `serve-mcp` command accepts the following options to customize the server's behavior: - **--path, --url** `string` (default: `.`) — Path to the local agents directory or a URL to a remote AIGNE project. - **--host** `string` (default: `localhost`) — Host to run the MCP server on. Use `0.0.0.0` to expose the server publicly to the network. - **--port** `number` (default: `3000`) — Port for the MCP server. The command respects the `PORT` environment variable if set; otherwise, it defaults to 3000. - **--pathname** `string` (default: `/mcp`) — The URL path for the MCP service endpoint. - **--aigne-hub-url** `string` — A custom AIGNE Hub service URL, used for fetching remote agent definitions or models. ## Examples ### Start a Server for a Local Project To serve agents from the current directory, run the command without any options. The server will start on the default host and port. **Start Server in Current Directory** ```bash aigne serve-mcp ``` Expected Output: **Console Output** ```text MCP server is running on http://localhost:3000/mcp ``` ### Serve Agents on a Specific Port and Path You can specify a different port and provide an explicit path to your AIGNE project directory. **Start Server with Custom Port and Path** ```bash aigne serve-mcp --path ./my-ai-project --port 8080 ``` Expected Output: **Console Output** ```text MCP server is running on http://localhost:8080/mcp ``` ### Expose the Server to the Network To make your MCP server accessible from other machines on your network, set the host to `0.0.0.0`. **Expose Server Publicly** ```bash aigne serve-mcp --host 0.0.0.0 ``` Expected Output: **Console Output** ```text MCP server is running on http://0.0.0.0:3000/mcp ``` ## Next Steps After exposing your agents via the MCP server, you might want to deploy them for production use. ::::card-group ::link-card{title="aigne deploy Command" description="Learn how to deploy your AIGNE application as a Blocklet." icon="navigation" href="/en/docs/aigne-cli/command-reference-deploy-cdbd13/"} ::link-card{title="Deploying Agents Guide" description="Follow a step-by-step tutorial for deploying your agents." icon="book-open" href="/en/docs/aigne-cli/guides-deploying-agents-cdbd13/"} :::: --- ## aigne test URL: https://www.arcblock.io/en/docs/aigne-cli/command-reference-test-cdbd13/ The `aigne test` command executes automated tests for your agents and skills. It provides a built-in mechanism for unit and integration testing to ensure your agents and the tools they rely on function correctly before deployment. ## Usage **Basic Syntax** ```bash aigne test [path] ``` ## Arguments | Argument | Description | |---|---| | `[path]` | Optional. The path to the directory containing your agents and their corresponding test files. If omitted, the command searches for tests in the current directory. | ## Description The command automatically discovers and runs test files within your project. For instance, the default AIGNE project template includes a `sandbox.test.js` file designed to verify the functionality of the `sandbox.js` skill. The `aigne test` command will execute such files to validate your agent's capabilities. ## Examples ### Run tests in the current directory To execute test cases for the AIGNE project located in your current working directory, run the command without any arguments: ```bash aigne test ``` ### Run tests in a specific directory If your agents are located in a different directory, you can specify the path to that directory: ```bash aigne test path/to/agents ``` ## Next Steps After ensuring your agents pass all tests, you can proceed to serve them for integration or deploy them as a service. ::::card-group ::link-card{title="aigne serve-mcp" description="Learn how to serve your agents as an MCP server for external integrations." icon="server" href="/en/docs/aigne-cli/command-reference-serve-mcp-cdbd13/"} ::link-card{title="aigne deploy" description="Learn how to deploy your AIGNE application as a Blocklet." icon="rocket" href="/en/docs/aigne-cli/command-reference-deploy-cdbd13/"} :::: --- ## Contributing URL: https://www.arcblock.io/en/docs/aigne-cli/contributing-cdbd13/ We're thrilled that you're interested in contributing to `@aigne/cli`! Your help is invaluable in making the AIGNE development experience better for everyone. Whether you're fixing a bug, proposing a new feature, or improving documentation, your contributions are welcome. This guide provides instructions for setting up your development environment, running tests, and submitting your changes. ## Getting Started The `@aigne/cli` package is part of the `aigne-framework` monorepo. To get started, you'll need to clone the main repository and install its dependencies. ### 1. Clone the Repository First, clone the `aigne-framework` repository from GitHub to your local machine: **Git Clone** ```bash git clone https://github.com/AIGNE-io/aigne-framework.git cd aigne-framework ``` ### 2. Install Dependencies We use `bun` as the primary package manager for the project. Install all the necessary dependencies from the root of the monorepo: **Bun Install** ```bash bun install ``` This will install all dependencies for every package in the monorepo, including `@aigne/cli`. ## Development Workflow All development commands for the CLI should be run from within its package directory: `packages/cli`. ### Building the Code To compile the TypeScript source code from `src/` into JavaScript in the `dist/` directory, run the build command. This process is configured by `tsconfig.build.json`. **Build Command** ```bash bun run build ``` ### Linting and Type Checking We use the TypeScript compiler to perform static analysis and ensure code quality. To check for any type errors without emitting JavaScript files, run the lint command: **Lint Command** ```bash bun run lint ``` ### Running Tests We have a comprehensive test suite to ensure the CLI functions correctly. The following scripts are available for testing: | Command | Description | |---|---| | `bun run test` | Executes the complete test suite, including tests for the CLI source (`test:src`) and the project templates (`test:templates`). | | `bun run test:src` | Runs only the unit and integration tests for the CLI's core functionality. | | `bun run test:templates` | Runs tests specifically for the project templates scaffolded by `aigne create`. | | `bun run test:coverage` | Runs the entire test suite and generates a code coverage report. | It's important to ensure all tests pass before submitting a pull request. ### Code Style We use [Prettier](https://prettier.io/) to maintain a consistent code style across the project. Please ensure your code is formatted before committing your changes. Most editors can be configured to format files automatically on save. ## Submitting a Pull Request Once you've made your changes and verified them with the build and test scripts, you're ready to submit a pull request. ::::steps :::step{title="Fork the repository"} on GitHub. ::: :::step{title="Create a new branch"} for your feature or bug fix: `git checkout -b your-feature-name`. ::: :::step{title="Commit your changes"} with a clear and descriptive commit message. ::: :::step{title="Push your branch"} to your fork: `git push origin your-feature-name`. ::: :::step{title="Open a pull request"} from your fork to the `main` branch of the `AIGNE-io/aigne-framework` repository. ::: :::step{title="Provide a detailed description"} of your changes in the pull request, referencing any related issues from the [issue tracker](https://github.com/AIGNE-io/aigne-framework/issues). ::: :::: We'll review your contribution as soon as possible. Thank you for helping us improve AIGNE! --- ## Agents and Skills URL: https://www.arcblock.io/en/docs/aigne-cli/core-concepts-agents-and-skills-cdbd13/ In the AIGNE ecosystem, Agents and Skills are the fundamental building blocks that bring your AI applications to life. They work together to create sophisticated, tool-augmented AI systems. Think of an Agent as the brain responsible for reasoning and conversation, and Skills as the tools it uses to perform actions and interact with the outside world. This section covers the definition and structure of these core components. For details on how to wire them together in your project, see the [Project Configuration (aigne.yaml)](/en/docs/aigne-cli/core-concepts-project-configuration-cdbd13/) documentation. ## Agents An Agent is the central component that processes user input, maintains context, and decides which actions to take. Its behavior is defined by a set of instructions (its core prompt) and the collection of Skills it has access to. Agents are typically defined in `.yaml` files. ### Agent Definition Example Here is a basic example of a chat agent that is equipped with a code execution skill. **chat.yaml** ```yaml name: chat description: Chat agent instructions: | You are a helpful assistant that can answer questions and provide information on a wide range of topics. Your goal is to assist users in finding the information they need and to engage in friendly conversation. input_key: message memory: true skills: - sandbox.js ``` ### Agent Properties The agent's behavior is configured through several key properties in its YAML definition file: | Property | Type | Description | |---|---|---| | `name` | `string` | A short, descriptive name for the agent. | | `description` | `string` | A more detailed explanation of the agent's purpose. | | `instructions` | `string` | The system prompt that defines the agent's personality, goals, and constraints. This is its core logic. | | `input_key` | `string` | The name of the property in the input object that contains the primary user message (e.g., `message`). | | `memory` | `boolean` | If `true`, the agent will retain conversation history, allowing for follow-up questions and context. | | `skills` | `array` | A list of skill files (e.g., `sandbox.js`) that the agent is authorized to use. | ## Skills A Skill is an executable function, typically written in JavaScript, that provides an Agent with a specific capability. This could be anything from running code, fetching data from an API, or interacting with a file system. Skills are the bridge between the Large Language Model's reasoning and the execution of concrete tasks. ### Skill Definition Example Skills are standard Node.js modules that export a default asynchronous function. Crucially, they also export metadata that describes their purpose and defines their input/output structure, allowing the agent to understand how and when to use them. **sandbox.js** ```javascript import vm from "node:vm"; export default async function evaluateJs({ code }) { const sandbox = {}; const context = vm.createContext(sandbox); const result = vm.runInContext(code, context, { displayErrors: true }); return { result }; } evaluateJs.description = "This agent evaluates JavaScript code."; evaluateJs.input_schema = { type: "object", properties: { code: { type: "string", description: "JavaScript code to evaluate" }, }, required: ["code"], }; evaluateJs.output_schema = { type: "object", properties: { result: { type: "any", description: "Result of the evaluated code" }, }, required: ["result"], }; ``` ### Skill Structure A skill file consists of three main parts: ::::steps :::step{title="Default Exported Function"} The core logic of the skill. It's an `async` function that receives an object of arguments and returns a result. ::: :::step{title="`description`"} A string property attached to the function that provides a natural language description of what the skill does. The agent's underlying LLM uses this description to determine when it's appropriate to call this skill. ::: :::step{title="`input_schema`"} / `output_schema`: JSON Schema objects that define the expected structure and types for the function's input and output. This ensures that the agent provides valid arguments and can correctly interpret the results. ::: :::: ## How They Work Together The interaction between a user, an agent, and a skill follows a clear pattern. The agent acts as an intelligent orchestrator, interpreting the user's request and invoking the appropriate skill to fulfill it. The following diagram illustrates this process: ![---labels: \[](https://media.arcblock.io/lib/a9/a9c71bead07cd4b1.w1600.webp) By separating the reasoning (Agent) from the execution (Skill), you can build powerful and extensible AI systems that are easy to maintain and upgrade. ### Next Steps Now that you understand the core concepts of Agents and Skills, you can proceed to the following sections: ::::card-group ::link-card{title="Project Configuration (aigne.yaml)" description="Learn how to configure agents, skills, and models in the main project configuration file." icon="file" href="/en/docs/aigne-cli/core-concepts-project-configuration-cdbd13/"} ::link-card{title="Creating a Custom Agent" description="Follow a step-by-step guide to build your own custom agent and integrate it as a skill." icon="sparkles" href="/en/docs/aigne-cli/guides-creating-a-custom-agent-cdbd13/"} :::: --- ## Core Concepts URL: https://www.arcblock.io/en/docs/aigne-cli/core-concepts-cdbd13/ ## labels: ["Reference"] An AIGNE project provides a structured environment for developing, testing, and deploying AI agents. At its heart, a project is a directory containing configuration files that define your agents, the skills they can use, and the language models they connect to. This section breaks down these fundamental building blocks. ## Project Structure When you create a new project using `aigne create`, it scaffolds a standard directory structure to keep your components organized. A typical project looks like this: **Project Structure** ```text my-agent-project/ ├── aigne.yaml # The main project configuration file. ├── agents/ # Directory for agent definition files. │ └── chat.yaml # Example agent definition. └── skills/ # Directory for skill implementation files. └── sandbox.js # Example skill implementation. ``` This structure separates configuration (`aigne.yaml`, `agents/`) from implementation (`skills/`), making your project modular and easy to manage. ## How It All Fits Together The following diagram illustrates the relationship between the core components of an AIGNE project. The central `aigne.yaml` file orchestrates everything, defining which agents exist, what skills they can use, and which AI model powers their intelligence. ![---](https://media.arcblock.io/lib/ec/ec34344a1f7784b9.w1600.webp) To understand how an AIGNE project works, it's essential to grasp its two primary components: the central project configuration and the executable agents and skills. Explore them in more detail below. ::::card-group ::link-card{title="Project Configuration (aigne.yaml)" description="This is the main manifest for your project. It defines the chat model to be used, lists the available agents, and registers the skills that those agents can access." icon="file" href="/en/docs/aigne-cli/core-concepts-project-configuration-cdbd13/"} ::link-card{title="Agents and Skills" description="Agents are the core actors that perform tasks, defined by their instructions and capabilities. Skills are the tools agents use, implemented as functions (e.g., JavaScript modules) that provide specific functionalities." icon="bot" href="/en/docs/aigne-cli/core-concepts-agents-and-skills-cdbd13/"} :::: With this foundational understanding, you're ready to dive deeper into how to configure your project. Next: Learn more about the main configuration file in the [Project Configuration (aigne.yaml)](/en/docs/aigne-cli/core-concepts-project-configuration-cdbd13/) guide. --- ## Project Configuration (aigne.yaml) URL: https://www.arcblock.io/en/docs/aigne-cli/core-concepts-project-configuration-cdbd13/ The `aigne.yaml` file is the heart of your AIGNE project. It serves as the central manifest, defining the project's metadata, language model settings, and the relationships between its core components like agents and skills. A well-structured `aigne.yaml` is the first step toward building a powerful and organized agent. This file uses the YAML format, which is designed to be human-readable and easy to write. ## Core Configuration Keys Let's break down the primary sections you'll find in a typical `aigne.yaml` file. ### Project Metadata These fields provide basic information about your project. - **name** `string` *(required)* — A unique identifier for your project. - **description** `string` — A brief summary of what your project does. **aigne.yaml** ```yaml name: test_aigne_project description: A test project for the aigne agent ``` ### Chat Model (chat_model) This is a critical section where you configure the Large Language Model (LLM) that will power your agents. AIGNE provides a flexible way to define the model provider, name, and other parameters. | Key | Type | Description | |---|---|---| | `provider` | string | The LLM provider (e.g., `openai`). Can also be specified as a prefix in the `model` key. | | `name` / `model` | string | The specific model to use (e.g., `gpt-4o-mini`). | | `temperature` | number | A value between 0 and 2 that controls the randomness of the model's output. Higher values result in more creative responses. | Here are a couple of common ways to configure the model: Example 1: Using `provider` and `name` This is a clear, explicit way to define the model. **aigne.yaml** ```yaml chat_model: provider: openai name: gpt-4o-mini temperature: 0.8 ``` Example 2: Using a prefixed `model` key This is a more concise shorthand format. **aigne.yaml** ```yaml chat_model: model: openai:gpt-4o-mini temperature: 0.8 ``` ### Agents (agents) The `agents` key lists all the agent definition files (`.yaml`) included in your project. Each file listed here defines the behavior, prompts, and tool usage for a specific agent. **aigne.yaml** ```yaml # ... other configurations agents: - chat.yaml ``` ### Skills (skills) The `skills` key lists the executable code or definitions that provide your agents with tools and capabilities. These can be JavaScript files (`.js`) containing functions or other YAML files that define complex skills. **aigne.yaml** ```yaml # ... other configurations skills: - sandbox.js - filesystem.yaml ``` ### Service and CLI Exposure You can also configure how your agents are exposed to the outside world, whether through a server or as command-line tools. - `mcp_server`: Configures which agents are served via the Model Context Protocol (MCP) when you run the `aigne serve-mcp` command. - `cli`: Configures which agents can be run directly from the command line. **aigne.yaml** ```yaml # ... other configurations mcp_server: agents: - chat.yaml cli: agents: - chat.yaml ``` ## Complete Example Here is a complete `aigne.yaml` file that brings all these elements together: **aigne.yaml** ```yaml name: test_aigne_project description: A test project for the aigne agent chat_model: model: openai:gpt-4o-mini temperature: 0.8 agents: - chat.yaml skills: - sandbox.js mcp_server: agents: - chat.yaml cli: agents: - chat.yaml ``` With this configuration file in place, you have a solid foundation for your project. The next step is to define what your agents and skills actually do. Now that you understand how to configure the project, let's explore the core components in more detail. Continue to the next section to learn about [Agents and Skills](/en/docs/aigne-cli/core-concepts-agents-and-skills-cdbd13/). --- ## Getting Started URL: https://www.arcblock.io/en/docs/aigne-cli/getting-started-cdbd13/ This guide will walk you through the essential steps to install the AIGNE CLI, create a new project, and run your first AI agent. By the end, you'll have a functioning agent running locally. ## Step 1: Install the AIGNE CLI First, you need to install the `@aigne/cli` package globally on your system. You can use your preferred JavaScript package manager. ### Using npm ```bash npm install -g @aigne/cli ``` ### Using yarn ```bash yarn global add @aigne/cli ``` ### Using pnpm ```bash pnpm add -g @aigne/cli ``` ## Step 2: Create a New Project Once the CLI is installed, you can create a new AIGNE project using the `aigne create` command. This command scaffolds a new directory with a default agent template, including all the necessary configuration files. ```bash aigne create my-first-agent ``` The CLI will then guide you through an interactive setup process. You'll be prompted to confirm the project name and select a template. For this guide, you can accept the default options by pressing Enter. ![Interactive project creation prompt](https://media.arcblock.io/lib/06/06e97c00fd2a53ff.w1600.webp) After the process completes, you'll see a success message with instructions on how to start using your new agent. ![Project creation success message](https://media.arcblock.io/lib/da/dacdbcdeba96a78e.w1600.webp) ## Step 3: Set Up Environment Variables Before running the agent, you need to configure your AI model provider's API key. First, navigate into your newly created project directory: ```bash cd my-first-agent ``` The project template includes an example environment file named `.env.local.example`. Copy it to a new file named `.env.local` to create your local configuration. ```bash cp .env.local.example .env.local ``` Now, open the `.env.local` file in your editor. You need to add your OpenAI API key. The default template is pre-configured to use OpenAI. **.env.local** ```shell # OpenAI MODEL="openai:gpt-4o-mini" OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` Replace `"YOUR_OPENAI_API_KEY"` with your actual key. ## Step 4: Run Your Agent With the configuration in place, you can now run your agent. Execute the `aigne run` command from within your project directory. ```bash aigne run ``` This command starts an interactive chat session with the default agent defined in your project. You can now start sending messages and interacting with your AI agent directly in the terminal. ![Running the default agent in chat mode](https://media.arcblock.io/lib/72/7259ac6078e7393b.w1600.webp) ## Next Steps Congratulations! You've successfully installed the AIGNE CLI, created a project, and run your first agent. To understand the files you've just created and how an AIGNE project is structured, head over to the [Core Concepts](/en/docs/aigne-cli/core-concepts-cdbd13/) section. --- ## Guides URL: https://www.arcblock.io/en/docs/aigne-cli/guides-cdbd13/ Welcome to the AIGNE CLI guides. This section provides practical, step-by-step tutorials designed to help you master common development workflows. Whether you're building your first custom agent, executing code from a remote repository, or preparing your application for production, these guides will provide you with the necessary instructions. ::::card-group ::link-card{title="Creating a Custom Agent" description="A step-by-step tutorial on creating a new JavaScript agent and integrating it into your project as a skill." icon="plus" href="/en/docs/aigne-cli/guides-creating-a-custom-agent-cdbd13/"} ::link-card{title="Running Remote Agents" description="Learn how to run agents directly from a remote Git repository or tarball URL." icon="globe" href="/en/docs/aigne-cli/guides-running-remote-agents-cdbd13/"} ::link-card{title="Deploying Agents" description="Learn how to deploy your AIGNE project as a Blocklet for production use." icon="rocket" href="/en/docs/aigne-cli/guides-deploying-agents-cdbd13/"} :::: For a detailed breakdown of every command and its available options, please refer to the comprehensive [Command Reference](/en/docs/aigne-cli/command-reference-cdbd13/). --- ## Creating a Custom Agent URL: https://www.arcblock.io/en/docs/aigne-cli/guides-creating-a-custom-agent-cdbd13/ This guide provides a step-by-step tutorial on creating a new JavaScript agent and integrating it into your AIGNE project as a skill. Agents are the core executable components that give your application its unique capabilities. By creating custom agents, you can extend the functionality of your AI to perform specialized tasks, interact with external APIs, or manipulate local data. ### Prerequisites Before you start, make sure you have an AIGNE project set up. If you don't, please follow our [Getting Started](/en/docs/aigne-cli/getting-started-cdbd13/) guide to create one first. ### Step 1: Create the Skill File A skill in AIGNE is a JavaScript module that exports a primary function and some metadata. This function contains the logic your agent will execute. Let's create a simple agent that generates a greeting. Create a new file named `greeter.js` in the root of your AIGNE project and add the following code: **greeter.js** ```javascript export default async function greet({ name }) { const message = `Hello, ${name}!`; console.log(message); return { message }; } greet.description = "A simple agent that returns a greeting message."; greet.input_schema = { type: "object", properties: { name: { type: "string", description: "The name to include in the greeting." }, }, required: ["name"], }; greet.output_schema = { type: "object", properties: { message: { type: "string", description: "The complete greeting message." }, }, required: ["message"], }; ``` Let's break down this file: - `export default async function greet({ name })`: This is the main function of your agent. It takes a single object as an argument, which contains the inputs defined in `input_schema`. It returns an object that must conform to the constraints defined by the `output_schema`. - `greet.description`: A plain-text description of what the agent does. This is crucial, as the main language model uses this description to understand when and how to use your tool. - `greet.input_schema`: A JSON Schema object that defines the expected input for your agent. This ensures that data passed to your function is valid. - `greet.output_schema`: A JSON Schema object that defines the expected output from your agent. ### Step 2: Integrate the Skill into Your Project Now that you've created the skill, you need to register it in your project's configuration file so the main chat agent can use it. 1. Open the `aigne.yaml` file in the root of your project. 2. Add your new `greeter.js` file to the `skills` list. **aigne.yaml** ```yaml chat_model: provider: openai name: gpt-4o-mini temperature: 0.8 agents: - chat.yaml skills: - sandbox.js - filesystem.yaml - greeter.js # Add your new skill here ``` By adding your script to this list, you make it available as a tool that the primary chat agent can invoke during a conversation. ### Step 3: Test Your Agent Directly With the skill created and registered, it's time to test it. You can execute any skill file directly from the command line using `aigne run`. Run the following command in your terminal: ```bash aigne run ./greeter.js --input '{"name": "AIGNE Developer"}' ``` This command executes your `greeter.js` script and passes the JSON string from the `--input` flag as an argument to the exported function. You should see the following output, confirming your agent works as expected: ```json { "result": { "message": "Hello, AIGNE Developer!" } } ``` ### Step 4: Use Your Agent in Chat Mode The real power of skills is unlocked when the main AI agent can decide to use them dynamically. To see this in action, run your project in interactive chat mode: ```bash aigne run --interactive ``` Once the chat session starts, ask the AI to use your new tool. For example: ``` > Use the greeter skill to say hello to the world. ``` The AI will recognize the request, find the `greeter` skill based on its description, and execute it with the correct parameters. It will then use the output from your skill to formulate its response. ### Next Steps Congratulations! You've successfully created a custom JavaScript agent, integrated it as a skill, and tested its functionality. You can now build more complex agents to connect to APIs, manage files, or perform any other task you can script. To learn how to share your project with others, check out our guide on [Deploying Agents](/en/docs/aigne-cli/guides-deploying-agents-cdbd13/). --- ## Deploying Agents URL: https://www.arcblock.io/en/docs/aigne-cli/guides-deploying-agents-cdbd13/ ## labels: ["Reference"] Deploying your AIGNE project transforms it from a local development setup into a self-contained, distributable application known as a Blocklet. This allows your agent to run in a production environment, be shared with others, and integrate seamlessly into the broader Blocklet ecosystem. The `aigne deploy` command automates this entire packaging and deployment process. This guide will walk you through the deployment workflow. For a detailed breakdown of all available command options, please see the [`aigne deploy` command reference](/en/docs/aigne-cli/command-reference-deploy-cdbd13/). ## The Deployment Process The `aigne deploy` command orchestrates a series of steps to prepare, configure, bundle, and deploy your agent. It leverages the `@blocklet/cli` under the hood to handle the complexities of Blocklet creation. Here is a high-level overview of the deployment flow: ![---](https://media.arcblock.io/lib/b2/b2bfd40289e38e74.w1600.webp) ### Step-by-Step Walkthrough To deploy your project, navigate to your project's root directory and run the deployment command, specifying the path to your project and the target endpoint. **Command** ```bash aigne deploy --path . --endpoint ``` Let's break down what happens when you execute this command: 1. Environment Preparation: The CLI first creates a temporary `.deploy` directory. It copies your project files into it, along with a standard Blocklet template. It then runs `npm install` inside this directory to fetch any necessary dependencies. 2. Blocklet CLI Check: The process verifies if `@blocklet/cli` is installed on your system. If not, it will prompt you for permission to install it globally. This is a one-time setup. ``` ? Install Blocklet CLI? › ❯ yes no ``` 3. Blocklet Configuration (First-time Deployment): If this is the first time you're deploying this project, the CLI will ask you for a name for your Blocklet. It suggests a default based on your agent's name in `aigne.yaml` or the project's folder name. ``` ? Please input agent blocklet name: › my-awesome-agent ``` After you provide a name, it automatically generates a new Decentralized Identifier (DID) for your Blocklet. This name and DID are saved locally in `~/.aigne/deployed.yaml`, so you won't be prompted for them on subsequent deployments of the same project. 4. Bundling: The CLI then invokes `blocklet bundle --create-release`, which packages your agent, its dependencies, and all necessary configuration into a single, deployable `.blocklet/bundle` file. 5. Deployment: Finally, the bundled application is pushed to your specified `--endpoint` using the `blocklet deploy` command. Once the process is complete, you'll see a confirmation message in your terminal. ``` ✅ Deploy completed: /path/to/your/project -> ``` Your AIGNE agent is now live as a Blocklet, ready to be run in a production environment. --- ## Running Remote Agents URL: https://www.arcblock.io/en/docs/aigne-cli/guides-running-remote-agents-cdbd13/ ## labels: ["Reference"] ## labels: ["Reference"] The AIGNE CLI is not limited to running projects from your local filesystem. It also provides a powerful feature to execute agents directly from a remote URL. This is incredibly useful for testing, sharing, and running agents without needing to clone a repository or manually download files. This guide will walk you through how to run agents from a remote source and explain the underlying caching mechanism. ## How It Works When you provide a URL to the `aigne run` command, the CLI performs the following steps automatically: ::::steps :::step{title="Download"} It fetches the package from the provided HTTP/HTTPS URL. ::: :::step{title="Cache"} The downloaded package is stored in a local cache directory (`~/.aigne/` by default). This speeds up subsequent runs of the same remote agent, as the CLI will use the cached version if it already exists. ::: :::step{title="Extract"} The CLI extracts the contents of the package (which is expected to be a tarball) into a working directory within the cache. ::: :::step{title="Execute"} Finally, it loads the AIGNE application from the extracted files and runs the specified agent just as it would with a local project. ::: :::: The entire process is streamlined to provide a seamless experience, making a remote agent feel as accessible as a local one. ![---](https://media.arcblock.io/lib/76/76a4277d8816a313.w1600.webp) ## Usage To run a remote agent, simply pass the URL pointing to a tarball (`.tar.gz`, `.tgz`) of an AIGNE project to the `aigne run` command. ### Basic Command **AIGNE CLI** ```bash # Run the default agent from a remote AIGNE project aigne run https://example.com/path/to/your/aigne-project.tar.gz ``` ### Running a Specific Agent If the remote project contains multiple agents, you can specify which one to run by adding its name after the URL. **AIGNE CLI** ```bash # Run a specific agent named 'my-agent' from the remote project aigne run https://example.com/path/to/your/aigne-project.tar.gz my-agent ``` Any additional arguments or options you provide will be passed directly to the remote agent. **AIGNE CLI** ```bash # Run a specific agent with additional options aigne run https://example.com/path/to/your/aigne-project.tar.gz my-agent --input "Hello, world!" ``` ## Caching AIGNE CLI automatically caches the downloaded remote agents to avoid re-downloading them on every run. - Default Location: The cache is stored in the `.aigne` directory within your home directory (e.g., `~/.aigne/`). The exact path within the cache is determined by the URL's hostname and path, ensuring that different remote agents are stored separately. - Overriding the Cache Directory: While the default location is suitable for most cases, you can specify a custom cache directory using the `--cache-dir` option. This can be useful for CI/CD environments or for managing different sets of cached agents. **AIGNE CLI** ```bash # Use a custom directory for caching the downloaded package aigne run https://example.com/path/to/your/aigne-project.tar.gz --cache-dir /tmp/aigne-cache ``` This powerful feature simplifies collaboration and distribution of AIGNE agents. You can now move on to learn how to deploy your agents for production use. :::action-card{title="Deploying Agents" description="Learn how to deploy your AIGNE project as a Blocklet for production use." icon="rocket"} ::action{label="Read Guide" href="/en/docs/aigne-cli/guides-deploying-agents-cdbd13/" variant="primary"} ::: --- ## Overview URL: https://www.arcblock.io/en/docs/aigne-cli/overview-cdbd13/ ![AIGNE Logo](https://media.arcblock.io/lib/58/580b6888d6e6d590.svg) Your command center for agent development `@aigne/cli` is the official command-line tool for the [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework), designed to streamline the entire lifecycle of agent development. It provides a comprehensive suite of commands to simplify project creation, local execution, testing, and deployment, enabling you to build, run, and manage AIGNE applications with ease. ## Key Features `@aigne/cli` is packed with features to accelerate your agent development workflow. ::::card-group ::link-card{title="Project Scaffolding" description="Quickly create new AIGNE projects with predefined file structures and configurations using the `aigne create` command." icon="folder-plus"} ::link-card{title="Local Agent Execution" description="Easily run and interact with your agents in a local chat loop for rapid testing and debugging via `aigne run`." icon="play"} ::link-card{title="Automated Testing" description="Leverage the built-in `aigne test` command for running unit and integration tests to ensure your agents are robust and reliable." icon="activity"} ::link-card{title="MCP Server Integration" description="Launch your agents as Model Context Protocol (MCP) servers, allowing them to be integrated with external systems." icon="server"} ::link-card{title="Rich Observability" description="Start a local server with `aigne observe` to view and analyze agent execution traces and performance data." icon="bar-chart"} ::link-card{title="Multi-Model Support" description="Seamlessly switch between different AI model providers, including OpenAI, Claude, XAI, and others." icon="bot"} :::: Ready to get started? Follow our [Getting Started](/en/docs/aigne-cli/getting-started-cdbd13/) guide to install the CLI and create your first AIGNE agent. --- ## AIGNE Framework URL: https://www.arcblock.io/en/docs/aigne-framework/ --- ## Agent Library URL: https://www.arcblock.io/en/docs/aigne-framework/agent-library-9dc03e/ The Agent Library provides a collection of pre-built, reusable agents designed to accelerate the development of complex AI applications. By integrating these ready-made components, you can easily orchestrate sophisticated workflows, manage concurrent tasks, and automate multi-step processes without building everything from the ground up. ## Introduction `@aigne/agent-library` is an official package for the AIGNE Framework that provides powerful, pre-built agent implementations. Built on `@aigne/core`, this library extends the framework's fundamental capabilities to simplify the orchestration of intricate agentic workflows, allowing developers to focus on high-level logic rather than foundational implementation details. Key features of the library include: - Advanced Agent Patterns: Offers high-level agent implementations, such as the `OrchestratorAgent`, for managing complex task execution flows. - Concurrent Task Execution: Supports the parallel execution of multiple tasks, significantly improving processing efficiency for demanding workloads. - Automated Planning: Capable of automatically generating step-by-step execution plans based on a high-level objective. - Result Synthesis: Intelligently aggregates and synthesizes results from various tasks and steps to produce a coherent final output. - Full TypeScript Support: Includes comprehensive type definitions to ensure a robust and type-safe development experience. ## Installation To get started, install the necessary packages using your preferred package manager. You will need both `@aigne/agent-library` and its core dependency, `@aigne/core`. **Install with npm** ```sh npm install @aigne/agent-library @aigne/core ``` **Install with yarn** ```sh yarn add @aigne/agent-library @aigne/core ``` **Install with pnpm** ```sh pnpm add @aigne/agent-library @aigne/core ``` ## Available Agents The library includes specialized agents designed for advanced use cases. Each agent is documented in its own section for detailed guidance. The following diagram illustrates the high-level architecture of the `OrchestratorAgent`: ![Agent Library](https://media.arcblock.io/lib/9a/9ada5d72a457aaf1.w1600.webp) ::::card-group ::link-card{title="Orchestrator Agent" description="An advanced agent that autonomously plans, executes, and synthesizes results for complex objectives. It uses a Planner → Worker → Completer architecture to coordinate multi-step workflows." icon="routes" href="/en/docs/aigne-framework/agent-library-orchestrator-9dc03e/"} :::: ## Summary The Agent Library is a vital toolkit for any developer looking to build sophisticated, multi-agent systems with the AIGNE Framework. It provides the foundational components for automating complex processes and orchestrating workflows efficiently. To dive deeper into the primary component of this library, proceed to the [Orchestrator](/en/docs/aigne-framework/agent-library-orchestrator-9dc03e/) documentation. --- ## Bash URL: https://www.arcblock.io/en/docs/aigne-framework/agent-library-bash-9dc03e/ This document details the Bash agent, which allows for the secure execution of shell scripts and command-line tools within an agentic workflow. You will learn how to configure its sandboxed environment, manage command permissions, and integrate it into your applications for system-level operations. ## Overview The Bash agent is designed to execute bash scripts within a controlled and secure environment. It leverages Anthropic's Sandbox Runtime to provide an isolated execution space, offering fine-grained control over system access, including network and filesystem operations. This makes it an ideal tool for tasks requiring file manipulation, process management, and automation of shell commands without compromising system security. Key features include: - Sandboxed Execution: Scripts are run in an isolated environment with configurable access controls for network and filesystem resources. - Command Permissions: A robust permission system allows you to whitelist, blacklist, or require approval for specific commands, preventing unauthorized operations. - Real-time Output: Standard output (`stdout`) and standard error (`stderr`) are streamed in real-time as the script executes. - Guard Agents: For commands requiring approval, you can designate another agent (an "AI guard") to dynamically approve or deny execution based on custom logic. > [!WARNING] > Sandbox mode is not supported on Windows. Windows users must explicitly set `sandbox: false` in their configuration to use the Bash agent. Disabling the sandbox removes all security protections and should only be done in trusted environments. ### Architecture The agent processes a script and, depending on whether the sandbox is enabled, either runs it directly or within the sandboxed environment. The output, including `stdout`, `stderr`, and the final `exitCode`, is streamed back to the caller. ```mermaid flowchart TB Input([Script Input]) --> BashAgent[Bash Agent] BashAgent --> SandboxCheck{SandboxEnabled?} SandboxCheck -->|Yes| Sandbox[Sandbox Execution] SandboxCheck -->|No| Direct[Direct Execution] Sandbox --> ShellProcess[Shell Process] Direct --> ShellProcess ShellProcess --> StreamOutput[Stream Output] StreamOutput --> Output([stdout, stderr, exitCode]) classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px classDef process fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px classDef decision fill:#E8F4F8,stroke:#4A9EBF,stroke-width:2px class Input,Output inputOutput class BashAgent,ShellProcess,StreamOutput process class SandboxCheck decision class Sandbox,Direct process ``` ## Basic Usage The most straightforward way to use the Bash Agent is by defining it in a YAML file. This allows you to configure its behavior declaratively. ### Standard Sandboxed Mode By default, the Bash agent runs in a secure, sandboxed environment. **bash-agent.yaml** ```yaml type: "@aigne/agent-library/bash" name: Bash # The input schema defines the 'script' parameter input_schema: type: object properties: script: type: string description: The bash script to execute. required: - script ``` You can then execute a script using the AIGNE CLI: ```bash aigne run . Bash --script 'echo "Hello from the Bash Agent!"' ``` ### Disabling the Sandbox For development, trusted environments, or on Windows, you can disable the sandbox. **bash-agent-no-sandbox.yaml** ```yaml type: "@aigne/agent-library/bash" name: Bash sandbox: false # Disable the sandbox input_schema: type: object properties: script: type: string description: The bash script to execute. required: - script ``` > [!CAUTION] > Disabling the sandbox removes all security protections. This should only be done in environments where you fully trust the scripts being executed. ## Configuration The Bash agent can be configured with several options to control its execution environment and security settings. - **sandbox** `object | boolean` (default: `true`) — Configuration for the sandboxed environment based on Anthropic's Sandbox Runtime. Set to false to disable sandboxing. Defaults to true with default restrictions. - **timeout** `number` (default: `60000`) — Execution timeout in milliseconds. The script will be terminated if it exceeds this limit. - **permissions** `object` — Configuration for command execution permissions, including allow, deny, defaultMode, and a guard agent. ### Input and Output The agent accepts a simple input object and produces a detailed output object. #### Input Schema - **script** `string` *(required)* — The bash script to be executed. #### Output Schema - **stdout** `string` — The standard output produced by the script. - **stderr** `string` — The standard error output produced by the script. - **exitCode** `number` — The exit code of the script. A value of `0` typically indicates success. ## Sandbox Configuration The sandbox provides a secure layer for script execution by restricting access to network and filesystem resources. ### Network Control You can specify which domains a script is allowed or forbidden to access. **network-config.yaml** ```yaml sandbox: network: # A list of allowed domains. Wildcards are supported. allowedDomains: - "api.github.com" - "*.example.com" # A list of denied domains, which takes precedence over the allow list. deniedDomains: - "*.ads.com" ``` ### Filesystem Control Define read and write permissions for specific paths or patterns. **filesystem-config.yaml** ```yaml sandbox: filesystem: # A list of paths where writing is permitted. allowWrite: - "./output" - "/tmp" # A list of paths where writing is forbidden. denyWrite: - "/etc" - "/usr" # A list of paths where reading is forbidden. denyRead: - "~/.ssh" - "*.key" ``` ## Permissions Configuration The permissions system controls which commands can be executed. It operates with a clear priority: `deny` rules override `allow` rules, and `allow` rules override the `defaultMode`. ### Permission Properties - **allow** `string[]` — A whitelist of commands that are permitted to execute without approval. Supports exact match (git status) and prefix matching with a wildcard (ls:*). - **deny** `string[]` — A blacklist of commands that are strictly forbidden. This list has the highest priority. - **defaultMode** `string` (default: `allow`) — The default behavior for commands not matching allow or deny lists. Possible values are allow, ask, or deny. - **guard** `Agent` — An agent invoked when defaultMode is ask. It receives the script and must return a boolean approved status. ### Example with a Guard Agent When `defaultMode` is set to `ask`, you must provide a `guard` agent to approve or reject commands. The guard agent receives the script as input and must return an object containing an `approved` boolean and an optional `reason` string. **guard-config.yaml** ```yaml type: "@aigne/agent-library/bash" name: Bash permissions: allow: - "echo:*" - "ls:*" deny: - "rm:*" - "sudo:*" defaultMode: "ask" guard: type: "ai" model: "anthropic/claude-3-5-sonnet-20241022" instructions: | You are a security guard for bash command execution. Analyze the requested script and decide whether to approve it. Script to evaluate: ```bash {{script}} ``` Approve safe, read-only operations. Deny any command that could modify or delete files, or alter system state. output_schema: type: object properties: approved: type: boolean description: Whether to approve the script execution. reason: type: string description: An explanation for the decision. required: - approved ``` ## Best Practices - Use the Sandbox: Always enable the sandbox in production environments to mitigate security risks. - Principle of Least Privilege: Configure sandbox and permission rules to grant only the minimum access necessary for the task. - Deny Dangerous Commands: Explicitly add destructive commands like `rm`, `sudo`, and `dd` to the `deny` list. - Handle Exit Codes: Check the `exitCode` in the agent's output to detect and handle script failures. An exit code other than `0` usually indicates an error, and details can be found in `stderr`. - Protect Sensitive Files: Use `denyRead` to prevent access to sensitive files and directories such as `~/.ssh`, `.env` files, and private keys. --- ## Orchestrator URL: https://www.arcblock.io/en/docs/aigne-framework/agent-library-orchestrator-9dc03e/ The Orchestrator agent provides a structured, reliable solution for managing complex, multi-step AI workflows. It breaks down high-level objectives into a series of manageable tasks, executes them sequentially, and synthesizes the results into a final, coherent response, enabling autonomous task planning and execution. This document details the architecture, configuration, and practical application of the Orchestrator agent. ## Overview The Orchestrator agent implements a sophisticated pattern for autonomous task management using a three-phase architecture: Planner → Worker → Completer. This structure allows it to handle complex objectives that require multiple steps, tools, and iterative refinement. The core components are: - Planner: Analyzes the main objective and the current progress to determine the most logical next task. - Worker: Executes the specific task assigned by the Planner, using any available tools or skills. - Completer: Once all tasks are finished, it reviews the entire execution history and synthesizes the individual results into a final, comprehensive output. - Execution State: A record-keeping component that tracks the history, status, and results of all tasks performed during the workflow. This iterative process continues until the Planner determines that the overall objective has been achieved. ## Architecture The workflow is a loop where the Planner and Worker collaborate until the objective is met, followed by a final synthesis step from the Completer. The following diagram illustrates this process: ![Orchestrator](https://media.arcblock.io/lib/81/81d32c36f1cad4b5.w1600.webp) The process unfolds as follows: ::::steps :::step{title="Initialization"} The Orchestrator receives a high-level objective and initializes an empty execution state. ::: :::step{title="Planning"} The Planner examines the objective and the current state (initially empty) and devises the first task. ::: :::step{title="Execution"} The Worker receives the task from the Planner and executes it. The outcome (success or failure, along with results or errors) is recorded. ::: :::step{title="State Update"} The result of the task is appended to the Execution State. ::: :::step{title="Iteration"} The process repeats from Step 2. The Planner now reviews the objective and the updated history in the Execution State to determine the next task. ::: :::step{title="Completion"} When the Planner decides the objective is complete, it signals the end of the loop. The Completer then takes over, reviews the full history in the Execution State, and generates the final response. ::: :::: ## Basic Usage The most direct method for configuring an Orchestrator agent is through a YAML definition file. ### Example Configuration Here is a basic setup to create an orchestrator that analyzes a project structure. **agents/orchestrator.yaml** ```yaml type: "@aigne/agent-library/orchestrator" name: orchestrator # Define the overall objective for the agent. # External files can be used for cleaner separation. objective: url: objective.md # Configure state management to control the workflow's execution. state_management: max_iterations: 20 # Set a limit on planning-execution cycles. max_tokens: 100000 # Set a token limit for the execution state context. keep_recent: 20 # Keep the 20 most recent tasks when compressing state. # Configure the Agent File System (AFS) to provide a workspace. afs: modules: - module: local-fs options: name: workspace localPath: . description: Workspace directory for the orchestrator agent. ``` The `objective.md` file contains the primary goal for the agent. **agents/objective.md** ```markdown Analyze the project structure and generate a comprehensive report. - Ignore node_modules, .git, dist, build directories. - Provide accurate information based on actual file contents. - Include key findings and recommendations. {% if message %} ## User Instructions {{ message }} {% endif %} ``` Finally, the main `aigne.yaml` file ties everything together. **aigne.yaml** ```yaml #!/usr/bin/env aigne model: google/gemini-1.5-pro agents: - agents/orchestrator.yaml ``` ## Configuration Reference The Orchestrator agent is configured through a set of options that define its behavior, components, and constraints. ### Top-Level Options - **objective** `PromptBuilder` *(required)* — The overall objective for the orchestrator to achieve. - **planner** `Agent` — A custom agent to handle the planning phase. If not provided, a default planner is used. - **worker** `Agent` — A custom agent to handle the execution phase. If not provided, a default worker is used. - **completer** `Agent` — A custom agent to handle the completion phase. If not provided, a default completer is used. - **stateManagement** `object` — Configuration for managing the execution state. - **inputSchema** `ZodSchema` — A schema to validate the input data. This is required if you use custom variables in your objective template. - **outputSchema** `ZodSchema` — A schema to validate the final output from the completer. - **afs** `AFSOptions` — Configuration for the Agent File System, making files and directories available to all components. - **skills** `Agent[]` — A list of tools or skills available to the worker agent. - **model** `string` — A default model to be used by all components (planner, worker, completer) unless overridden in a component's specific configuration. > [!NOTE] > When using custom input variables like `{{ message }}` in your `objective` prompt, you must declare them in the `inputSchema`. Any undeclared variable will not be passed to the template. ### StateManagementOptions These options control the execution loop and prevent infinite runs or context overflow. - **maxIterations** `number` (default: `20`) — The maximum number of planning-execution cycles to perform. - **maxTokens** `number` — The maximum number of tokens allowed for the execution state history passed to the agents. - **keepRecent** `number` — The number of recent tasks to retain when the state is compressed due to token limits. ## Customizing Components You can replace the default Planner, Worker, or Completer with your own custom agents to tailor the orchestrator's logic to a specific domain. This is typically done by creating an AI agent with custom instructions. ### Custom Planner The Planner's role is to decide the next action. - Standard Input: `objective`, `skills`, `executionState`. - Standard Output: An object containing `nextTask` (string) and `finished` (boolean). Example Configuration: **agents/orchestrator.yaml** ```yaml type: "@aigne/agent-library/orchestrator" objective: url: objective.md planner: type: ai instructions: url: custom-planner.md ``` Example Instructions (`custom-planner.md`): ```markdown ## Your Role You are a strategic planner for code analysis tasks. Your responsibility is to decide the next single task to perform based on the overall objective and the history of completed tasks. ## Objective {{ objective }} ## Available Skills {{ skills | yaml.stringify }} ## Current Execution State {{ executionState | yaml.stringify }} ## Planning Guidelines - Review `executionState` to avoid repeating work. - Decompose the objective into small, logical steps. - Plan only one task at a time. - If all work is done, set `finished: true`. ## Output Format Return a JSON object with the following fields: - `nextTask`: A string describing the next task to execute. Omit this field if finished. - `finished`: A boolean indicating if the objective is complete. ``` ### Custom Worker The Worker's role is to execute a single task. - Standard Input: `objective`, `task`, `executionState`. - Standard Output: An object containing `success` (boolean), `result` (string, on success), and `error` (object with `message`, on failure). Example Configuration: **agents/orchestrator.yaml** ```yaml # ... worker: type: ai instructions: url: custom-worker.md ``` Example Instructions (`custom-worker.md`): ```markdown ## Your Role You are a professional code analysis worker. Your job is to execute the assigned task using the available tools. ## Overall Objective (For Context Only) {{ objective }} ## Current Task {{ task }} ## Execution Guidelines - Focus strictly on completing the `Current Task`. - Use the provided tools and skills to accomplish the task. - If successful, provide the result. If not, explain the failure in the error message. ## Output Format Return a JSON object with the following fields: - `success`: A boolean indicating if the task succeeded. - `result`: A string with the task's output. Required on success. - `error`: An object with a `message` field. Required on failure. ``` ### Custom Completer The Completer's role is to synthesize the final report. - Standard Input: `objective`, `executionState`. - Standard Output: A user-defined structure, validated against the orchestrator's `output_schema`. Example Configuration: **agents/orchestrator.yaml** ```yaml # ... completer: type: ai instructions: url: custom-completer.md output_schema: type: object properties: summary: type: string description: An executive summary of the findings. recommendations: type: array items: type: string description: A list of actionable recommendations. required: [summary] ``` Example Instructions (`custom-completer.md`): ```markdown ## Your Role You are responsible for synthesizing all task results from the execution history into a final, structured response. ## User Objective {{ objective }} ## Execution Results {{ executionState | yaml.stringify }} ## Synthesis Guidelines - Analyze all successful and failed tasks in `executionState`. - Consolidate the individual results into a coherent report. - Structure your response according to the defined output schema. ## Output Format Return a JSON object conforming to the output schema. ``` ## Best Practices To maximize the effectiveness of the Orchestrator agent, adhere to the following principles. ### 1. Define Clear Objectives Provide specific, actionable, and unambiguous objectives. A well-defined goal is critical for the Planner to create a logical task sequence. - Good: "Analyze the authentication system in `/src/auth`, identify security vulnerabilities, and provide specific recommendations for each issue found." - Poor: "Look at the code and tell me what's wrong." ### 2. Specialize Component Roles Ensure each component focuses on its designated role. The Planner should only plan, not execute. The Worker should only execute its current task, not plan future ones. ### 3. Use State Compression for Long Workflows For complex objectives that may require many iterations, configure state management to prevent the context from becoming too large for the model. ```yaml state_management: max_iterations: 50 max_tokens: 80000 # Prevent context overflow keep_recent: 25 # Keep recent task history for context ``` ### 4. Use Different Models for Different Components Optimize for cost and performance by assigning different models to each component based on its needs. A powerful model for planning and synthesis, and a faster, cheaper model for execution, is often a cost-effective strategy. ```yaml planner: type: ai model: anthropic/claude-3-5-sonnet-20240620 worker: type: ai model: google/gemini-1.5-flash completer: type: ai model: anthropic/claude-3-5-sonnet-20240620 ``` ### 5. Validate Inputs and Outputs Use `input_schema` and `output_schema` to enforce type safety and ensure the agent receives and produces data in the expected format. This is especially critical when the objective prompt uses template variables. --- ## Advanced Topics URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-advanced-topics-9dc03e/ After mastering the core concepts and building basic applications, you are ready to explore the more sophisticated features of the AIGNE Framework. This section is designed for developers seeking to build complex, robust, and highly customized AI applications. Here, we will delve into advanced patterns and tools that provide greater control over agent definition, prompt engineering, execution lifecycle, and data handling. The following topics provide in-depth guides to leveraging these advanced capabilities. Understanding them will enable you to move from simple agentic workflows to building enterprise-grade AI systems. ::::card-group ::link-card{title="Defining Agents with YAML" description="Learn how to define and configure agents declaratively using YAML files. This approach separates configuration from code, making your agentic systems easier to manage, version, and deploy." icon="file" href="/en/docs/aigne-framework/developer-guide-advanced-topics-defining-agents-with-yaml-9dc03e/"} ::link-card{title="Prompts" description="Dive deep into dynamic prompt management with the PromptBuilder. This guide covers using Nunjucks templating to create flexible, reusable, and context-aware prompts for your AI models." icon="terminal" href="/en/docs/aigne-framework/developer-guide-advanced-topics-prompts-9dc03e/"} ::link-card{title="Hooks" description="Understand the agent execution lifecycle and how to intercept it with hooks. Learn to add custom logic, logging, or monitoring at various stages like onStart, onEnd, and onSkillStart." icon="git-pull-request" href="/en/docs/aigne-framework/developer-guide-advanced-topics-hooks-9dc03e/"} ::link-card{title="Streaming" description="Discover how to process real-time, streaming responses from agents. This is essential for creating responsive, conversational applications that deliver information as it becomes available." icon="chevrons-right" href="/en/docs/aigne-framework/developer-guide-advanced-topics-streaming-9dc03e/"} :::: ## Summary This section provides the tools and techniques necessary to elevate your AI applications. By leveraging declarative definitions, dynamic prompts, lifecycle hooks, and streaming, you can build more powerful, maintainable, and efficient agentic systems. For further details, please proceed to the specific sub-sections linked above. To see how these components fit into the broader architecture, refer to the [Core Concepts](/en/docs/aigne-framework/developer-guide-core-concepts-9dc03e/) documentation. --- ## Defining Agents with YAML URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-advanced-topics-defining-agents-with-yaml-9dc03e/ The AIGNE Framework supports a declarative approach for defining agents using YAML configuration files. This method separates the agent's definition (its properties, instructions, and skills) from the application's business logic, promoting better organization, reusability, and easier management of complex agentic systems. This guide provides a comprehensive overview of the YAML syntax for defining various agent types and their properties. ## Basic Structure Every agent definition, regardless of its type, is contained within a `.yaml` file. The `type` attribute is the primary discriminator that determines the agent's behavior and required properties. If the `type` is omitted, it defaults to `ai`. Here is a fundamental example of an AI agent configuration: **chat.yaml** ```yaml name: Basic Chat Agent description: A simple agent that responds to user messages. type: ai instructions: "You are a helpful assistant. Respond to the user's message concisely." input_key: message skills: - my-skill.js ``` ### Core Properties The following properties are common across most agent types: - **name** `string` — A human-readable name for the agent. - **description** `string` — A brief description of the agent's purpose and capabilities. - **type** `string` (default: `ai`) — Specifies the agent's type. Determines the required fields and behavior. Valid types include ai, image, team, transform, mcp, and function. - **model** `object | string` — Configuration for the chat model used by the agent, overriding any globally defined model. Can be a string or a detailed object. - **skills** `array` — A list of other agents or JavaScript/TypeScript functions that this agent can use as tools. Each skill is referenced by its file path. - **inputSchema** `object | string` — A JSON schema defining the expected input structure. Can be an inline object or a path to an external .json or .yaml file. - **outputSchema** `object | string` — A JSON schema for structuring the agent's output. Can be an inline object or a path to an external file. This is crucial for enabling structured output. - **memory** `boolean | object` — Enables statefulness for the agent. Set to true for default memory or provide a configuration object for specific providers. - **hooks** `array` — Defines lifecycle hooks (onStart, onSuccess, onError, onEnd) that trigger other agents at different stages of execution. ## Loading External Prompts and Schemas To maintain clean and modular configurations, you can load agent instructions and schemas from external files. This is particularly useful for complex prompts or reusable data structures. ### External Instructions For `ai` and `image` agents, instructions can be lengthy. You can define them in a separate Markdown or text file and reference it using the `url` key. **chat-with-prompt.yaml** ```yaml name: chat-with-prompt description: An AI agent with instructions loaded from an external file. type: ai instructions: url: prompts/main-prompt.md input_key: message memory: true skills: - skills/sandbox.js ``` The `main-prompt.md` file contains the raw text that will be used as the agent's system prompt. **prompts/main-prompt.md** ```markdown You are a master programmer. When the user asks for code, provide a complete, runnable example and explain the key parts. ``` You can also construct a multi-part prompt with different roles: **multi-role-prompt.yaml** ```yaml instructions: - role: system url: prompts/system-role.md - role: user content: "Here is an example of a good response:" - role: assistant url: prompts/example-response.md ``` ### External Schemas Similarly, `inputSchema` and `outputSchema` can reference external JSON or YAML files that define the schema structure. **structured-output-agent.yaml** ```yaml name: JSON Extractor type: ai instructions: Extract the user's name and email from the text. outputSchema: schemas/user-schema.yaml ``` The `user-schema.yaml` file would contain the JSON schema definition: **schemas/user-schema.yaml** ```yaml type: object properties: name: type: string description: The full name of the user. email: type: string description: The email address of the user. required: - name - email ``` ## Agent Type Specifics The following sections detail the unique configuration properties for each agent type. ### AI Agent (type: ai) The `AIAgent` is the most common type, designed for general-purpose interaction with language models. **ai-agent-example.yaml** ```yaml type: ai name: Customer Support AI instructions: url: prompts/support-prompt.md input_key: customer_query output_key: response # Enforce the model to call a specific skill tool_choice: "sandbox" outputSchema: schemas/support-response.yaml skills: - sandbox.js ``` - **instructions** `string | object | array` — The system prompt or instructions for the AI model. Can be a simple string, a reference to an external file (url), or an array of message objects (role, content/url). - **inputKey** `string` — The key in the input object that contains the main user message to be sent to the model. - **outputKey** `string` — The key under which the AI's final text response will be placed in the output object. - **toolChoice** `string` — Forces the model to use a specific skill (tool). The value must match the name of a skill attached to the agent. ### Team Agent (type: team) The `TeamAgent` orchestrates a collection of child agents (defined under `skills`) to perform a multi-step task. **team-agent-example.yaml** ```yaml type: team name: Research and Write Team # Agents will run one after another mode: sequential # The output of this team will be the collected outputs of all steps include_all_steps_output: true skills: - url: agents/researcher.yaml - url: agents/writer.yaml - url: agents/editor.yaml ``` - **mode** `string` (default: `sequential`) — The execution mode for the team. Can be sequential (agents run in order) or parallel (agents run concurrently). - **iterateOn** `string` — The key in the input object containing an array. The team will execute its workflow for each item in the array. - **reflection** `object` — Configures a self-correction loop where a reviewer agent inspects the output and can trigger re-runs until the output is approved. ### Image Agent (type: image) The `ImageAgent` is specialized for generating images using an image model. **image-agent-example.yaml** ```yaml type: image name: Logo Generator instructions: "A minimalist, flat-design logo for a tech startup named 'Innovate'." # Pass through specific options to the image model provider model_options: quality: hd style: vivid ``` - **instructions** `string | object` *(required)* — The prompt describing the desired image. Unlike the AI agent, this is a mandatory field. - **modelOptions** `object` — A key-value map of provider-specific options to control image generation (e.g., quality, style, size). ### Transform Agent (type: transform) The `TransformAgent` uses a [JSONata](https://jsonata.org/) expression to declaratively map, filter, or restructure JSON data without writing code. **transform-agent-example.yaml** ```yaml type: transform name: User Formatter description: Extracts and formats user names from a list. jsonata: "payload.users.{'name': firstName & ' ' & lastName}" ``` - **jsonata** `string` *(required)* — The JSONata expression to execute against the input data. ## Summary Defining agents via YAML offers a powerful, declarative alternative to programmatic definition. It allows for clear separation of concerns, enhances reusability, and simplifies the management of agent configurations. By leveraging external files for prompts and schemas, you can build complex, modular, and maintainable AI systems. For more hands-on examples, refer to the other guides in the [Advanced Topics](/en/docs/aigne-framework/developer-guide-advanced-topics-9dc03e/) section. --- ## Hooks URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-advanced-topics-hooks-9dc03e/ Hooks provide a powerful mechanism to observe, intercept, and inject custom logic into an agent's execution lifecycle. They allow you to add functionalities like logging, monitoring, input/output transformation, and custom error handling without altering the core implementation of an agent. This guide details the agent execution lifecycle, the available hooks, and how to implement them effectively. ## Agent Execution Lifecycle Understanding the agent's execution lifecycle is crucial for using hooks correctly. When an agent is invoked, it proceeds through a series of steps, with hooks being triggered at specific points. The following diagram illustrates the sequence of events and the corresponding hooks that are called during an agent's invocation. ![Hooks](https://media.arcblock.io/lib/27/27bf289dc972d118.w1600.webp) ## Available Hooks Hooks are defined within an `AgentHooks` object. Each hook can be implemented as either a function or a separate, dedicated agent. - **onStart** `function | Agent` — Triggered at the very beginning of an agent's invocation, before input validation. It can be used to modify the initial input or options. - **onSuccess** `function | Agent` — Triggered after the agent's process method completes successfully and the output has been validated. It can be used to transform the final output. - **onError** `function | Agent` — Triggered when an error is thrown during any stage of the execution. It can be used to implement custom error logging or a retry mechanism by returning { retry: true }. - **onEnd** `function | Agent` — Triggered at the very end of an agent's invocation, regardless of whether it succeeded or failed. It's suitable for cleanup tasks, final logging, or metric collection. - **onSkillStart** `function | Agent` — Triggered just before an agent invokes one of its skills (a sub-agent). This is useful for tracing the delegation of tasks between agents. - **onSkillEnd** `function | Agent` — Triggered after a skill invocation completes, whether it succeeds or fails. It receives the skill's result or the error. - **onHandoff** `function | Agent` — Triggered when an agent's process method returns another agent instance, effectively handing off control. This allows for monitoring of agent-to-agent transfers. ## Implementing Hooks Hooks can be attached to an agent in three ways: 1. During agent instantiation via the `hooks` property in `AgentOptions`. 2. At invocation time via the `hooks` property in `AgentInvokeOptions`. 3. Globally on the `AIGNEContext` instance. ### Example 1: Basic Logging Here is a simple example of a hook that logs the start and end of an agent's execution. **Agent Logging Hook** ```typescript import { Agent, AIGNE, type AgentHooks } from "@aigne/core"; // Define the logging hook const loggingHook: AgentHooks = { onStart: ({ agent, input }) => { console.log(`[${agent.name}] Starting execution with input:`, input); }, onEnd: ({ agent, input, output, error }) => { if (error) { console.error(`[${agent.name}] Execution failed for input:`, input, "Error:", error); } else { console.log(`[${agent.name}] Execution succeeded with output:`, output); } }, }; // Define a simple agent class MyAgent extends Agent { async process(input: { message: string }) { return { reply: `You said: ${input.message}` }; } } // Instantiate the agent with the hook const myAgent = new MyAgent({ name: "EchoAgent", hooks: [loggingHook], }); const aigne = new AIGNE(); await aigne.invoke(myAgent, { message: "hello" }); // Console Output: // [EchoAgent] Starting execution with input: { message: 'hello' } // [EchoAgent] Execution succeeded with output: { reply: 'You said: hello' } ``` ### Example 2: Modifying Input with onStart The `onStart` hook can return an object to modify the `input` that the agent will receive. **Modifying Agent Input** ```typescript import { Agent, AIGNE, type AgentHooks } from "@aigne/core"; const inputModificationHook: AgentHooks = { onStart: ({ input }) => { // Add a timestamp to the input message const newInput = { ...input, timestamp: new Date().toISOString(), }; return { input: newInput }; }, }; class GreeterAgent extends Agent { async process(input: { name: string; timestamp?: string }) { return { greeting: `Hello, ${input.name}! (processed at ${input.timestamp})` }; } } const agent = new GreeterAgent({ hooks: [inputModificationHook] }); const aigne = new AIGNE(); const result = await aigne.invoke(agent, { name: "Alice" }); console.log(result); // { // greeting: "Hello, Alice! (processed at 2023-10-27T10:00:00.000Z)" // } ``` ### Example 3: Custom Retry with onError The `onError` hook can return `{ retry: true }` to signal that the AIGNE should re-attempt the agent's `process` method. This is useful for handling transient failures. **Custom Retry Hook** ```typescript import { Agent, AIGNE, type AgentHooks } from "@aigne/core"; let attempt = 0; const retryHook: AgentHooks = { onError: ({ agent, error }) => { console.log(`[${agent.name}] Attempt failed: ${error.message}. Retrying...`); // Return true to signal a retry, but only for the first 2 attempts if (attempt < 2) { return { retry: true }; } // Return nothing to let the error propagate }, }; class UnreliableAgent extends Agent { async process() { attempt++; if (attempt <= 2) { throw new Error("Service temporarily unavailable"); } return { status: "OK" }; } } const agent = new UnreliableAgent({ hooks: [retryHook] }); const aigne = new AIGNE(); const result = await aigne.invoke(agent, {}); console.log(result); // { status: 'OK' } ``` This agent will fail twice, and the `retryHook` will intercept the error and trigger a retry each time. On the third attempt, the agent succeeds. ## Hook Priority Hooks can be defined on the agent, at invocation, and on the context. To manage the order of execution, hooks can have a `priority` property set to `"high"`, `"medium"`, or `"low"` (default). Hooks are executed in the order of their priority: `high` > `medium` > `low`. **Hook Priority Example** ```typescript const highPriorityHook: AgentHooks = { priority: 'high', onStart: () => console.log('High priority hook executed.'), }; const mediumPriorityHook: AgentHooks = { priority: 'medium', onStart: () => console.log('Medium priority hook executed.'), }; const lowPriorityHook: AgentHooks = { // priority defaults to 'low' onStart: () => console.log('Low priority hook executed.'), }; class MonitoredAgent extends Agent { async process(input: {}) { console.log('Agent processing...'); return { success: true }; } } const agent = new MonitoredAgent({ hooks: [lowPriorityHook, highPriorityHook, mediumPriorityHook], }); const aigne = new AIGNE(); await aigne.invoke(agent, {}); // Console Output: // High priority hook executed. // Medium priority hook executed. // Low priority hook executed. // Agent processing... ``` This predictable execution order is essential when one hook's logic depends on the outcome of another. ## Summary Hooks are an essential tool for building robust and observable agent-based systems. They provide a clean, non-invasive way to add cross-cutting concerns like logging, instrumentation, and resilience patterns to your agents. By understanding the agent lifecycle and the capabilities of each hook, you can create sophisticated, production-ready AI applications. --- ## Prompts URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-advanced-topics-prompts-9dc03e/ Effective communication with AI models is contingent upon the quality and structure of the prompts provided. The AIGNE framework supplies a robust system for creating dynamic, reusable, and structured prompts through its `PromptBuilder` class and the integrated Nunjucks templating engine. This guide provides a systematic explanation of these components. Refer to the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) documentation for more context on how prompts are utilized within agents. ## Prompt Templating with Nunjucks The framework utilizes the [Nunjucks templating engine](https://mozilla.github.io/nunjucks/) to facilitate the creation of dynamic prompts. This allows for the injection of variables, inclusion of external files, and other programmatic logic directly within your prompt files. All prompt text is processed by the `PromptTemplate` class, which uses Nunjucks to render the final string. ### Variable Substitution You can define placeholders in your prompts using the `{{ variable_name }}` syntax. These placeholders are replaced with actual values at runtime. **analyst-prompt.md** ```markdown Analyze the following data: {{ data }} ``` When invoking an agent with this prompt, you would provide the `data` variable in the input message. **index.ts** ```typescript import { AIGNE, AIAgent } from "@aigne/core"; import { OpenAI }s from "@aigne/openai"; const model = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const aigne = new AIGNE({ model, agents: { analyst: new AIAgent({ instructions: { path: "./analyst-prompt.md" }, inputKey: "data", }), }, }); const result = await aigne.invoke("analyst", { data: "User feedback scores: 8, 9, 7, 10, 6.", }); console.log(result); ``` ### File Inclusion Nunjucks allows for the composition of prompts from multiple files using the `{% include "path/to/file.md" %}` tag. This is highly effective for reusing common instructions or components across different prompts. Paths are resolved relative to the file containing the `include` tag. For example, you can define a common set of instructions in one file and include it in another. **common-instructions.md** ```markdown Always respond in a professional and factual manner. Do not speculate or provide opinions. ``` **main-prompt.md** ```markdown You are an expert financial analyst. {% include "./common-instructions.md" %} Analyze the quarterly earnings report provided. ``` This modular approach simplifies prompt management and ensures consistency. ## Structuring Prompts with ChatMessageTemplate For chat-based models, prompts are structured as a sequence of messages, each with a specific role. The framework provides classes to represent these messages programmatically. - `SystemMessageTemplate`: Sets the context or high-level instructions for the AI model. - `UserMessageTemplate`: Represents a message from the end-user. - `AgentMessageTemplate`: Represents a previous response from the AI model, useful for few-shot prompting or continuing a conversation. - `ToolMessageTemplate`: Represents the result of a tool call made by the agent. These templates can be combined into a `ChatMessagesTemplate` to define a complete conversational prompt. **structured-prompt.ts** ```typescript import { ChatMessagesTemplate, SystemMessageTemplate, UserMessageTemplate, } from "@aigne/core"; const promptTemplate = new ChatMessagesTemplate([ SystemMessageTemplate.from( "You are a helpful assistant that translates {{ input_language }} to {{ output_language }}." ), UserMessageTemplate.from("{{ text }}"), ]); // This template can then be used in an AIAgent's `instructions`. ``` ## The PromptBuilder Class The `PromptBuilder` is the central component responsible for assembling the final, complete prompt that is sent to the language model. It orchestrates the entire process, integrating various inputs into a coherent structure. The following diagram illustrates the flow of information into the `PromptBuilder`:direction: right style { stroke-width: 2 font-size: 14 } "User Input (Message)": { shape: document style.fill: "#D1E7DD" } "Prompt Template (.md)": { shape: document style.fill: "#D1E7DD" } "Agent Configuration": { shape: document style.fill: "#D1E7DD" } Context: { shape: document style.fill: "#D1E7DD" } PromptBuilder: { shape: hexagon style.fill: "#A9CCE3" } "ChatModelInput (to LLM)": { shape: document style.fill: "#FADBD8" } "User Input (Message)" -> PromptBuilder "Prompt Template (.md)" -> PromptBuilder "Agent Configuration" -> PromptBuilder Context -> PromptBuilder PromptBuilder -> "ChatModelInput (to LLM)" "Agent Configuration".children: { "Skills/Tools" Memory "Output Schema" } "ChatModelInput (to LLM)".children: { "Rendered Messages" "Tool Definitions" "Response Format" } The `PromptBuilder` automatically performs the following actions during the `build` process: ::::steps :::step{title="Load Instructions"} It loads the prompt template from a string, a file path, or an MCP `GetPromptResult` object. ::: :::step{title="Render Templates"} It uses Nunjucks to format the prompt templates, injecting variables from the user's input message. ::: :::step{title="Inject Memory"} If the agent is configured to use memory, the `PromptBuilder` retrieves relevant memories and converts them into system, user, or agent messages to provide conversational context. ::: :::step{title="Incorporate Tools (Skills)"} It gathers all available skills (from the agent configuration and the invocation context) and formats them into the `tools` and `tool_choice` parameters for the model. ::: :::step{title="Define Response Format"} If the agent has an `outputSchema`, the `PromptBuilder` configures the model's `responseFormat` to enforce structured JSON output. ::: :::: ### Instantiation The most common method for creating a `PromptBuilder` is via the static `PromptBuilder.from()` method, which can accept different sources: - From a string: ```typescript const builder = PromptBuilder.from("You are a helpful assistant."); ``` - From a file path: ```typescript const builder = PromptBuilder.from({ path: "./prompts/my-prompt.md" }); ``` When an `AIAgent` is defined with `instructions`, it internally uses `PromptBuilder.from()` to create and manage the prompt building process. ## Summary The AIGNE framework provides a layered and powerful system for prompt engineering. By understanding and utilizing `PromptTemplate` with Nunjucks for dynamic content and `PromptBuilder` for orchestrating the final structure, you can create sophisticated, modular, and effective prompts for your AI agents. For further reading, explore the [AIAgent documentation](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) to see how these prompts are integrated into the agent lifecycle. --- ## Streaming URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-advanced-topics-streaming-9dc03e/ The AIGNE Framework provides robust support for handling streaming responses from agents. This is particularly useful for applications requiring real-time data processing, such as chatbots, live data feeds, or any user interface that benefits from immediate, incremental updates. By processing data as it becomes available, you can create more responsive and interactive user experiences. This guide details the methodology for enabling and consuming streamed responses within the framework. ## Enabling Streaming To receive a streamed response from an agent, you must set the `stream` option to `true` in the `invoke` call. When this option is enabled, the `invoke` method returns an `AgentResponseStream`, which is a `ReadableStream` of `AgentResponseChunk` objects, instead of a fully formed response object. **AIGNE Invoke with Streaming** ```typescript import { AIGNE, AIAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; const llm = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o", }); const agent = new AIAgent({ model: llm, instructions: "You are a helpful assistant.", }); const aigne = new AIGNE({ model: llm, agents: { agent }, }); async function run() { // Enable streaming by setting the `stream` option to true const stream = await aigne.invoke("agent", { prompt: "Tell me a short story.", }, { stream: true }); // The 'stream' variable is now a ReadableStream for await (const chunk of stream) { // Process each chunk as it arrives process.stdout.write(chunk.delta.text?.text || ""); } } run(); ``` ## Consuming the Stream The returned stream consists of `AgentResponseChunk` objects. Each chunk represents a piece of the total response. There are two primary types of data within a chunk's `delta`: - `delta.text`: Contains partial text content. This is used for streaming text from language models. - `delta.json`: Contains partial JSON data. This is used when an agent is configured to return structured output. The framework incrementally builds the final JSON object. ### Processing Chunks You can iterate over the stream using a `for await...of` loop to process each chunk as it arrives. The following example demonstrates how to accumulate both text and the final structured JSON from a stream. **Processing Stream Chunks** ```typescript import { AIGNE, AIAgent, Message } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; import { agentResponseStreamToObject } from "@aigne/core/utils"; // Assume aigne and agent are configured as in the previous example interface StoryOutput extends Message { protagonist: string; setting: string; plotSummary: string; storyText: string; } async function processStream() { const aigne = new AIGNE({ model: new OpenAI(), agents: { agent: new AIAgent({ model: new OpenAI(), }) }, }); const stream = await aigne.invoke("agent", { prompt: "Write a short story about a robot who discovers music. Return the protagonist's name, the setting, a plot summary, and the full story text.", // Assuming the agent is configured for structured output }, { stream: true } ); let fullText = ""; const finalResult: Partial = {}; for await (const chunk of stream) { if (chunk.delta.text?.storyText) { const partialText = chunk.delta.text.storyText; fullText += partialText; process.stdout.write(partialText); // Live update UI with text } if (chunk.delta.json) { // The framework provides the partially-merged JSON object in each relevant chunk Object.assign(finalResult, chunk.delta.json); } } console.log("\n\n--- Final Structured Output ---"); console.log(finalResult); // You can also use a utility to get the final object directly // Note: This consumes the stream, so it should be used instead of the loop // const finalObject = await agentResponseStreamToObject(stream); // console.log(finalObject); } processStream(); ``` ## Utility: agentResponseStreamToObject If you only need the final, fully-formed object and do not need to process intermediate chunks, the framework provides the `agentResponseStreamToObject` utility. This function consumes the entire stream and returns a single promise that resolves with the complete response object. This is useful when you want the benefits of streaming on the backend (e.g., lower time-to-first-byte from the LLM) but only need to deliver the final result to the caller. **Using agentResponseStreamToObject** ```typescript import { AIGNE, AIAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; import { agentResponseStreamToObject } from "@aigne/core/utils"; // ... setup aigne and agent async function getFinalObject() { const aigne = new AIGNE({ model: new OpenAI(), agents: { agent: new AIAgent({ model: new OpenAI(), }) }, }); const stream = await aigne.invoke("agent", { prompt: "Tell me a short story.", }, { stream: true }); // Consumes the stream and returns the final aggregated object const result = await agentResponseStreamToObject(stream); console.log("--- Complete Response ---"); console.log(result.text); } getFinalObject(); ``` ## Streaming to the Frontend with Server-Sent Events (SSE) A common use case for streaming is to send real-time updates to a web frontend. The AIGNE framework simplifies this by providing an `AgentResponseStreamSSE` class, which converts an `AgentResponseStream` into a format compatible with Server-Sent Events (SSE). ### Data Flow Diagram The following diagram illustrates the data flow from the backend AIGNE to the frontend application when using SSE. ![Streaming](https://media.arcblock.io/lib/38/38e4538ab9fc4068.w1600.webp) ### Backend Implementation On your server, create an endpoint that initiates the agent `invoke` call with streaming enabled. Then, pipe the resulting `AgentResponseStream` into an `AgentResponseStreamSSE` and write its output to the HTTP response. The example below uses a generic web server structure. **SSE Backend Endpoint** ```typescript import { AIGNE, AIAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; import { AgentResponseStreamSSE } from "@aigne/core/utils"; // ... setup aigne // Example using a generic server context (e.g., Express, Hono, etc.) async function handleSseRequest(req, res) { const aigne = new AIGNE({ model: new OpenAI(), agents: { agent: new AIAgent({ model: new OpenAI(), }) }, }); res.writeHead(200, { "Content-Type": "text/event-stream", "Connection": "keep-alive", "Cache-Control": "no-cache", }); try { const stream = await aigne.invoke("agent", { prompt: req.body.prompt, }, { stream: true }); // Convert the agent stream to an SSE stream const sseStream = new AgentResponseStreamSSE(stream); // Pipe the SSE stream to the HTTP response for await (const sseChunk of sseStream) { res.write(sseChunk); } } catch (error) { console.error("SSE stream error:", error); const sseError = `event: error\ndata: ${JSON.stringify({ message: error.message })}\n\n`; res.write(sseError); } finally { res.end(); } } ``` ### Frontend Implementation On the frontend, use the native `EventSource` API to connect to your SSE endpoint. You can then listen for `message` events to receive chunks and `error` events to handle issues. **SSE Frontend Client** ```javascript const promptInput = document.getElementById('prompt-input'); const submitButton = document.getElementById('submit-button'); const responseContainer = document.getElementById('response'); submitButton.addEventListener('click', async () => { const prompt = promptInput.value; responseContainer.innerHTML = ''; // Clear previous response const eventSource = new EventSource('/api/chat-stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt }), }); eventSource.onmessage = (event) => { const chunk = JSON.parse(event.data); if (chunk.delta?.text?.text) { responseContainer.innerHTML += chunk.delta.text.text; } }; eventSource.onerror = (error) => { console.error('EventSource failed:', error); responseContainer.innerHTML += '

Error receiving stream.

'; eventSource.close(); }; // The 'open' event fires when the connection is established eventSource.onopen = () => { console.log('Connection to server opened.'); }; }); ``` This architecture enables building highly responsive UIs where text appears word-by-word, exactly as it is generated by the AI model. ## Summary The streaming capabilities of the AIGNE Framework are essential for building modern, real-time AI applications. By enabling the `stream` option in the `invoke` method, you can process data incrementally, improve perceived performance, and efficiently pipe agent responses to frontends using Server-Sent Events. For further details on agent invocation, refer to the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) documentation. --- ## Agent Types URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-9dc03e/ The AIGNE Framework provides a suite of specialized agent types, each designed to perform a specific function. While all agents inherit from the base `Agent` class, these specialized implementations offer pre-built capabilities for common tasks, from interacting with AI models to orchestrating complex workflows. Understanding these types is key to building robust and efficient applications. This section provides a high-level overview of the available agent types. For detailed implementation, configuration options, and code examples, please refer to the specific sub-document for each agent. ![Agent Types](https://media.arcblock.io/lib/7d/7dab44a0402c2fe2.w1600.webp) ## Available Agent Types The framework includes the following specialized agents, each tailored for a distinct purpose. ::::card-group ::link-card{title="AI Agent" description="The primary agent for interacting with large language models (LLMs). It handles prompt construction, model invocation, and processing of AI-generated responses, including tool usage." icon="bot" href="/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/"} ::link-card{title="Team Agent" description="Orchestrates a group of agents to work together. It can manage workflows in sequential or parallel modes, enabling complex, multi-step problem-solving." icon="users" href="/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/"} ::link-card{title="Image Agent" description="A specialized agent for interfacing with image generation models. It takes instructional prompts and generates visual content." icon="image" href="/en/docs/aigne-framework/developer-guide-agents-image-agent-9dc03e/"} ::link-card{title="Function Agent" description="Wraps standard TypeScript or JavaScript functions, allowing you to integrate any custom code or business logic seamlessly into an agentic workflow." icon="code" href="/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/"} ::link-card{title="Transform Agent" description="Performs declarative data transformations using JSONata expressions. It is ideal for mapping, restructuring, and converting data between different formats without writing procedural code." icon="move" href="/en/docs/aigne-framework/developer-guide-agents-transform-agent-9dc03e/"} ::link-card{title="MCP Agent" description="Connects to external systems and tools via the Model Context Protocol (MCP). This agent acts as a bridge, allowing your application to leverage external resources and capabilities." icon="zap" href="/en/docs/aigne-framework/developer-guide-agents-mcp-agent-9dc03e/"} :::: ## Summary Choosing the correct agent type for a given task is a fundamental step in designing an effective AIGNE application. Each agent is a specialized tool designed for a specific job. By composing these agents, you can build sophisticated systems capable of handling a wide range of tasks. For a deeper understanding of each agent's capabilities and configuration, please proceed to the detailed documentation for each type. - Next: Learn about the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/), the core component for interacting with language models. --- ## AI Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/ The `AIAgent` is the primary component for interacting with large language models (LLMs). It serves as a direct interface to a `ChatModel`, enabling sophisticated conversational AI, function calling (tool usage), and structured data extraction. This agent handles the complexities of prompt construction, model invocation, response parsing, and tool execution loops. This guide provides a comprehensive overview of the `AIAgent`, its configuration, and its core functionalities. For a broader understanding of how agents fit into the AIGNE framework, please refer to the [Agents core concept guide](/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/). ## How It Works The `AIAgent` follows a systematic process to handle user input and generate a response. This process often involves multiple interactions with an LLM, especially when tools are used. ![AI Agent](https://media.arcblock.io/lib/f2/f2f932af73db4d9c.w1600.webp) The diagram above illustrates the typical lifecycle of a request: 1. Prompt Construction: The `AIAgent` uses a `PromptBuilder` to assemble the final prompt from its `instructions`, the user input, and the history of any previous tool calls. 2. Model Invocation: The fully formed prompt is sent to the configured `ChatModel`. 3. Response Parsing: The agent receives the model's raw output. 4. Tool Call Detection: It checks if the response contains a request to call a tool. 5. - If No, the agent formats the text response and returns it. - If Yes, it proceeds to the tool execution loop. 6. Tool Execution: The agent identifies and invokes the requested tool (which is another agent), captures its output, and formats it into a message for the model. The process then loops back to step 1, sending the tool's result back to the model for the next generation step. 7. Final Output: Once the model generates a final text response without any tool calls, the agent formats it and streams it back to the user. ## Configuration An `AIAgent` is configured through its constructor options. Below is a detailed breakdown of the available parameters. - **instructions** `string | PromptBuilder` — The core directive that guides the AI model's behavior. This can be a simple string or a PromptBuilder instance for creating complex, dynamic prompts. See the Prompts guide for more details. - **inputKey** `string` — Specifies which key from the input message object should be treated as the main user query. If not set, instructions must be provided. - **outputKey** `string` (default: `message`) — Defines the key under which the agent's final text response will be placed in the output object. Defaults to message. - **inputFileKey** `string` — Specifies the key from the input message that contains file data to be sent to the model. - **outputFileKey** `string` (default: `files`) — Defines the key under which any files generated by the model will be placed in the output object. Defaults to files. - **toolChoice** `AIAgentToolChoice | Agent` (default: `auto`) — Controls how the agent uses its available tools (skills). See the Tool Usage section below for details. - **toolCallsConcurrency** `number` (default: `1`) — The maximum number of tool calls that can be executed concurrently in a single turn. - **catchToolsError** `boolean` (default: `true`) — If true, the agent will catch errors from tool executions and feed the error message back to the model. If false, an error will halt the entire process. - **structuredStreamMode** `boolean` (default: `false`) — Enables a mode for extracting structured JSON data from the model's streaming response. See the Structured Output section for more information. - **memoryAgentsAsTools** `boolean` (default: `false`) — When true, attached MemoryAgent instances are exposed to the model as callable tools, allowing the agent to explicitly read from or write to its memory. ### Basic Example Here is an example of a simple `AIAgent` configured to act as a helpful assistant. **Basic Chat Agent** ```javascript import { AIAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; // Configure the model to use const model = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o", }); // Create the AI Agent const chatAgent = new AIAgent({ instructions: "You are a helpful assistant.", inputKey: "question", outputKey: "answer", }); // To run the agent, you would use the AIGNE's invoke method // const aigne = new AIGNE({ model }); // const response = await aigne.invoke(chatAgent, { question: "What is AIGNE?" }); // console.log(response.answer); ``` This agent takes an input object with a `question` key and produces an output object with an `answer` key. ## Tool Usage A powerful feature of `AIAgent` is its ability to use other agents as tools. By providing a list of `skills` during invocation, the `AIAgent` can decide to call these tools to gather information or perform actions. The `toolChoice` option dictates this behavior. | `toolChoice` Value | Description | |---|---| | `auto` | (Default) The model decides whether to call a tool based on the context of the conversation. | | `none` | Disables tool usage entirely. The model will not attempt to call any tools. | | `required` | Forces the model to call one or more tools. | | `router` | A specialized mode where the model is forced to choose exactly one tool. The agent then directly routes the request to that tool and streams its response as the final output. This is highly efficient for creating dispatcher agents. | ### Tool Usage Example Imagine you have a `FunctionAgent` that can fetch weather information. You can provide this to an `AIAgent` as a skill. **Agent with a Tool** ```javascript import { AIAgent, FunctionAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; // A simple function to get the weather function getCurrentWeather(location) { if (location.toLowerCase().includes("tokyo")) { return JSON.stringify({ location: "Tokyo", temperature: "15", unit: "celsius" }); } return JSON.stringify({ location, temperature: "unknown" }); } // Wrap the function in a FunctionAgent to make it a tool const weatherTool = new FunctionAgent({ name: "get_current_weather", description: "Get the current weather in a given location", inputSchema: { type: "object", properties: { location: { type: "string", description: "The city and state" } }, required: ["location"], }, process: ({ location }) => getCurrentWeather(location), }); // Configure the model const model = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o", }); // Create an AI Agent that can use the weather tool const weatherAssistant = new AIAgent({ instructions: "You are a helpful assistant that can provide weather forecasts.", inputKey: "query", outputKey: "response", }); // When invoking, provide the tool as a skill // const aigne = new AIGNE({ model, skills: [weatherTool] }); // const result = await aigne.invoke(weatherAssistant, { query: "What's the weather like in Tokyo?" }); // console.log(result.response); // The LLM will respond using the tool's output ``` In this scenario, the `AIAgent` will receive the query, recognize the need for weather information, call the `weatherTool`, receive its JSON output, and then use that data to formulate a natural language response. ## Structured Output For tasks that require extracting specific, structured information (like sentiment analysis, classification, or entity extraction), `structuredStreamMode` is invaluable. When enabled, the agent actively parses the model's streaming output to find and extract a JSON object. By default, the model must be instructed to place its structured data inside `...` tags in YAML format. ### Structured Output Example This example configures an agent to analyze the sentiment of a user message and return a structured JSON object. **Structured Sentiment Analysis** ```javascript import { AIAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; const sentimentAnalyzer = new AIAgent({ instructions: ` Analyze the sentiment of the user's message. Respond with a single word summary, followed by a structured analysis. Place the structured analysis in YAML format inside tags. The structure should contain 'sentiment' (positive, negative, or neutral) and a 'score' from -1.0 to 1.0. `, inputKey: "message", outputKey: "summary", structuredStreamMode: true, }); // When invoked, the output will contain both the text summary // and the parsed JSON object. // const aigne = new AIGNE({ model: new OpenAI(...) }); // const result = await aigne.invoke(sentimentAnalyzer, { message: "AIGNE is an amazing framework!" }); /* Expected result: { summary: "Positive.", sentiment: "positive", score: 0.9 } */ ``` You can customize the parsing logic, including the start/end tags and the parsing function (e.g., to support JSON directly), using the `customStructuredStreamInstructions` option. ## Summary The `AIAgent` is a foundational building block for creating advanced AI applications. It provides a robust and flexible interface to language models, complete with support for tool usage, structured data extraction, and memory integration. For more complex workflows, you may need to orchestrate multiple agents. To learn how, proceed to the [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/) documentation. For advanced prompt templating techniques, see the [Prompts](/en/docs/aigne-framework/developer-guide-advanced-topics-prompts-9dc03e/) guide. --- ## Function Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/ The `FunctionAgent` provides a straightforward method for encapsulating existing TypeScript or JavaScript functions, thereby elevating them to first-class agents within the AIGNE framework. This enables the seamless integration of custom business logic, external API interactions, or any arbitrary code into an agentic workflow, obviating the need for extensive boilerplate. By wrapping a function, the `FunctionAgent` allows it to participate fully in the agent ecosystem. It can be invoked identically to any other agent, incorporated as a skill within an `AIAgent` or `TeamAgent`, and interact with the AIGNE context and lifecycle hooks. This positions it as an essential component for bridging conventional programmatic logic with AI-driven processes. This diagram illustrates the creation and invocation flow of a `FunctionAgent`, from providing the source function to receiving the final output. ![Function Agent](https://media.arcblock.io/lib/d4/d429b7c7edff24dc.w1600.webp) ## Key Concepts A `FunctionAgent` is a specialized implementation of the `Agent` class that delegates its core processing logic to a user-supplied function. The primary constructor for this agent is the static method `FunctionAgent.from()`, which streamlines its instantiation. A `FunctionAgent` can be created in two ways: ::::steps :::step{title="Directly from a function:"} Pass a synchronous or asynchronous function to `FunctionAgent.from()`. The agent will infer properties, such as its name, from the function definition. ::: :::step{title="From a configuration object:"} For more explicit control, provide an options object that specifies the `process` function along with other standard agent configurations like `name`, `description`, `inputSchema`, and `outputSchema`. ::: :::: This design provides flexibility for both rapid, ad-hoc integrations and the development of robust, well-defined agent components. ## Creating a Function Agent The standard method for creating a `FunctionAgent` is through the `FunctionAgent.from()` factory method, which accepts either a function or a configuration object. ### From a Simple Function Any standard function can be wrapped directly. The AIGNE framework will use the function's name as the agent's name. This approach is optimal for simple, self-contained operations. **Wrapping a Simple Function** ```javascript import { FunctionAgent } from "@aigne/core"; // Define a simple synchronous function function add({ a, b }) { return { result: a + b }; } // Wrap the function into an agent const addAgent = FunctionAgent.from(add); console.log(addAgent.name); // Outputs: 'add' ``` The function receives the agent's input object as its first argument and is expected to return an object that constitutes the agent's output. ### With Full Configuration For more complex integrations, a full configuration object should be provided. This allows for the definition of input/output schemas for validation, the inclusion of a description, and the assignment of a custom name. This method is recommended for creating robust and reusable agents. **Function Agent with Configuration** ```javascript import { FunctionAgent } from "@aigne/core"; import { z } from "zod"; const fetchUserAgent = FunctionAgent.from({ name: "FetchUser", description: "Fetches user data from a placeholder API.", inputSchema: z.object({ userId: z.number().describe("The ID of the user to fetch."), }), outputSchema: z.object({ id: z.number(), name: z.string(), email: z.string().email(), }), process: async ({ userId }) => { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`); if (!response.ok) { throw new Error("Failed to fetch user data."); } const data = await response.json(); return { id: data.id, name: data.name, email: data.email, }; }, }); ``` In this example, `zod` schemas are defined to ensure the input `userId` is a number and the output conforms to a specified structure. ## Invoking a Function Agent A created `FunctionAgent` is invoked using the standard `.invoke()` method, consistent with all other agent types. **Invoking the Agent** ```javascript async function main() { // Using the simple 'add' agent from the previous example const result = await addAgent.invoke({ a: 10, b: 5 }); console.log(result); // { result: 15 } // Using the configured 'FetchUser' agent const user = await fetchUserAgent.invoke({ userId: 1 }); console.log(user); // { id: 1, name: 'Leanne Graham', email: 'Sincere@april.biz' } } main(); ``` The `invoke` method manages the execution lifecycle, including input validation against the schema (if provided), execution of the underlying function, and validation of the result against the output schema. ## Advanced Usage ### Streaming Responses `FunctionAgent` supports streaming responses through the use of asynchronous generators. The `process` function can be defined as an `async function*` that `yield`s `AgentResponseChunk` objects, enabling incremental data transmission. **Streaming with an Async Generator** ```javascript import { FunctionAgent, jsonDelta, textDelta } from "@aigne/core"; import { z } from "zod"; const streamNumbersAgent = FunctionAgent.from({ name: "StreamNumbers", inputSchema: z.object({ count: z.number().int().positive(), }), outputSchema: z.object({ finalCount: z.number(), message: z.string(), }), process: async function* ({ count }) { for (let i = 1; i <= count; i++) { yield textDelta({ message: `Processing number ${i}... ` }); await new Promise((resolve) => setTimeout(resolve, 200)); // Simulate work } yield jsonDelta({ finalCount: count }); yield textDelta({ message: "Done." }); }, }); async function runStream() { const stream = await streamNumbersAgent.invoke({ count: 5 }, { streaming: true }); for await (const chunk of stream) { console.log(chunk); } } runStream(); ``` This capability is particularly useful for long-running tasks where providing real-time feedback on the agent's progress is required. ## Configuration The `FunctionAgent` is initialized via a configuration object passed to `FunctionAgent.from` or its constructor. The following parameters are specific to its configuration. - **process** `FunctionAgentFn` *(required)* — The function that implements the agent's logic. It receives the input message and invocation options and returns the processing result. This can be a synchronous function, an async function returning a Promise, or an async generator for streaming. - **name** `string` — A unique name for the agent, used for identification and logging. If not provided, it defaults to the name of the process function. - **description** `string` — A human-readable description of what the agent does. This is useful for documentation and for other agents to understand its capabilities. - **inputSchema** `ZodObject` — A Zod schema to validate the structure and types of the input message. If validation fails, the agent will throw an error before the process function is called. - **outputSchema** `ZodObject` — A Zod schema to validate the structure and types of the output message returned by the process function. If validation fails, an error is thrown. All other properties from the base `AgentOptions` are also available. Refer to the [Agent documentation](/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/) for a complete list. ## Summary The `FunctionAgent` is a versatile tool for integrating conventional code into the AIGNE framework, acting as a bridge that allows any JavaScript or TypeScript function to operate as a standard agent. - Simplicity: Wrap existing functions with minimal effort using `FunctionAgent.from()`. - Integration: Seamlessly incorporate traditional business logic, calculations, or external API calls into agentic workflows. - Validation: Enforce data contracts and improve reliability by defining input and output schemas with Zod. - Flexibility: Supports synchronous functions, asynchronous promises, and streaming with async generators. By leveraging `FunctionAgent`, developers can combine the deterministic and reliable nature of traditional code with the dynamic capabilities of AI agents to build more powerful and robust applications. For orchestrating multiple agents, including Function Agents, refer to the documentation on the [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/). --- ## Image Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-image-agent-9dc03e/ The `ImageAgent` is a specialized agent responsible for generating images. It acts as an interface to an `ImageModel`, processing input data to formulate a prompt and then requesting the image generation service to create an image. This agent is essential for any workflow that requires the dynamic creation of visual content based on textual descriptions. It leverages a `PromptBuilder` to construct its prompts, enabling the use of templates to generate images from variable inputs. The following diagram illustrates the invocation flow of the `ImageAgent`, from user request to final output: ![Image Agent](https://media.arcblock.io/lib/0b/0b20a799ad9d4783.w1600.webp) ## Configuration An `ImageAgent` can be configured either programmatically using TypeScript or declaratively using YAML. Both methods require defining the instructions for image generation and optionally specifying model-specific parameters. ### TypeScript Configuration To create an `ImageAgent` in TypeScript, use the static `ImageAgent.from()` method and provide it with `ImageAgentOptions`. **"ImageAgent Configuration"** ```typescript import { AIGNE, ImageAgent } from "@aigne/core"; import { OpenAI } from "@aigne/openai"; // Configure the image model provider const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); // Create an instance of the ImageAgent const architectAgent = ImageAgent.from({ name: "architect", description: "An agent that draws architectural diagrams.", instructions: "Create an architectural diagram of a {{subject}}.", modelOptions: { quality: "hd", style: "vivid", }, }); // The AIGNE instance must have an imageModel configured const aigne = new AIGNE({ imageModel: openai.image("dall-e-3"), }); async function run() { const result = await aigne.invoke(architectAgent, { input: { subject: "microservices application", }, }); console.log(result); } run(); ``` The code above defines an `ImageAgent` named "architect". It uses a templated `instructions` string to generate a prompt. The `modelOptions` object passes specific parameters to the underlying DALL-E 3 model to request a high-definition, vivid image. ### YAML Configuration Alternatively, you can define an `ImageAgent` in a `.yaml` file. This approach is useful for separating agent definitions from application logic. **"image-agent.yaml"** ```yaml type: image name: style-artist description: Draws an image of an object in a specific style. instructions: | Draw an image of a {{object}} in the {{style}} style. input_schema: type: object properties: object: type: string description: The object to draw. style: type: string description: The style of the image. required: - object - style ``` In this declarative example, the `type: image` specifies that this is an `ImageAgent`. The `instructions` field contains a multi-line string with placeholders (`{{object}}`, `{{style}}`) that will be populated from the input during invocation. The `input_schema` formally defines the expected input structure. ## Parameters The behavior of an `ImageAgent` is controlled by the options provided during its construction. - **instructions** `string | PromptBuilder` *(required)* — The prompt template used for image generation. This can be a simple string or a PromptBuilder instance for more complex logic. Placeholders in the format {{key}} will be replaced with values from the input object. - **modelOptions** `Record` — An object containing provider-specific parameters to pass to the underlying ImageModel. This allows for fine-tuned control over the generation process, such as specifying image quality, size, or style. Refer to the specific model provider's documentation for available options. - **outputFileType** `'url' | 'base64'` — Specifies the desired format for the output image. The default behavior is determined by the ImageModel, but you can explicitly request either a public URL (url) or a Base64-encoded string (base64). ## Invocation and Output When an `ImageAgent` is invoked, it passes the input to its `PromptBuilder` to generate the final prompt. It then calls the configured `ImageModel` with this prompt and any specified `modelOptions`. The agent's output is an object conforming to the `ImageModelOutput` schema, which contains the generated image in the requested format. Example Invocation **"Invoking the Agent"** ```typescript const result = await aigne.invoke(styleArtistAgent, { // Assuming styleArtistAgent is loaded from YAML input: { object: "futuristic city", style: "cyberpunk", }, }); ``` Example Response **"ImageAgent Output"** ```json { "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/...", "base64": null } ``` The response contains a `url` pointing to the generated image. If `outputFileType` were set to `'base64'`, the `base64` field would be populated instead. ## Summary The `ImageAgent` provides a structured and reusable way to integrate image generation capabilities into your AI workflows. By separating the prompt logic from the model interaction, it allows for clear and maintainable agent designs. For more information on other agent types, refer to the following documentation: - [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/): For interacting with language models. - [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/): For orchestrating multiple agents. - [Function Agent](/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/): For wrapping custom code as an agent. --- ## MCP Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-mcp-agent-9dc03e/ The `MCPAgent` is a specialized agent designed to interact with external systems that adhere to the Model Context Protocol (MCP). It acts as a bridge, allowing your AIGNE application to connect to remote MCP servers and utilize their capabilities—such as tools, prompts, and resources—as if they were native components of the framework. This enables seamless integration with a wide range of external services, from database connectors and web automation tools to proprietary enterprise systems, provided they expose an MCP-compliant interface. Key functionalities include: - Multiple Transport Protocols: Connect to MCP servers via standard I/O (`stdio`), Server-Sent Events (`sse`), or `streamableHttp`. - Automatic Discovery: Automatically discovers and registers the tools, prompts, and resources available on the connected MCP server. - Robust Connection Management: Features automatic reconnection for network-based transports to handle transient connectivity issues. ## How MCPAgent Works The `MCPAgent` encapsulates the logic for connecting to an MCP server and translating its offerings into AIGNE constructs. When an `MCPAgent` is initialized, it connects to the specified server and queries for its available tools, prompts, and resources. These are then dynamically attached to the agent instance as `skills`, `prompts`, and `resources`, respectively, making them directly accessible within your AIGNE workflows. ![MCP Agent](https://media.arcblock.io/lib/88/88a479edb2df72c0.w1600.webp) ## Creating an MCPAgent You can create an `MCPAgent` instance using the static `MCPAgent.from()` method. This factory method supports several configuration patterns depending on how you need to connect to the MCP server. ### 1. Connecting via Standard I/O (Stdio) This method is ideal for running an MCP server as a local child process. The `MCPAgent` communicates with the server through its standard input and output streams. - **command** `string` *(required)* — The command to execute to start the MCP server process. - **args** `string[]` — An array of string arguments to pass to the command. - **env** `Record` — Environment variables to set for the child process. **Connecting to a Local Filesystem Server** ```javascript import { MCPAgent } from "@aigne/core"; // Create an MCPAgent by running a command-line server await using mcpAgent = await MCPAgent.from({ command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "."], }); console.log('Connected to:', mcpAgent.name); // Access the skills provided by the filesystem server const fileReader = mcpAgent.skills.read_file; if (fileReader) { const result = await fileReader.invoke({ path: "./package.json" }); console.log(result); } ``` ### 2. Connecting via Network (SSE or StreamableHTTP) This is the standard method for connecting to remote MCP servers over a network. You can choose between two transport protocols: - `sse`: Server-Sent Events, a simple and widely supported protocol for streaming. - `streamableHttp`: A more advanced, bidirectional streaming protocol. - **url** `string` *(required)* — The URL of the remote MCP server endpoint. - **transport** `'sse' | 'streamableHttp'` (default: `sse`) — The transport protocol to use. Defaults to sse. - **opts** `object` — Additional options to pass to the underlying transport client (e.g., for headers and authentication). - **timeout** `number` (default: `60000`) — Request timeout in milliseconds. - **maxReconnects** `number` (default: `10`) — The maximum number of times to attempt reconnection if the connection is lost. Set to 0 to disable. - **shouldReconnect** `(error: Error) => boolean` — A function that returns true if a reconnect should be attempted based on the error received. **Connecting via StreamableHTTP** ```javascript import { MCPAgent } from "@aigne/core"; // Create an MCPAgent using a StreamableHTTP server connection await using mcpAgent = await MCPAgent.from({ url: `http://localhost:3000/mcp`, transport: "streamableHttp", }); console.log('Connected to:', mcpAgent.name); const echoSkill = mcpAgent.skills.echo; if (echoSkill) { const result = await echoSkill.invoke({ message: "Hello, World!" }); console.log(result); } ``` ### 3. Using a Pre-configured Client If you have already instantiated and configured an MCP `Client` object, you can pass it directly to create an `MCPAgent`. This is useful for advanced scenarios where you need fine-grained control over the client's configuration. - **client** `Client` *(required)* — A pre-configured instance of an MCP Client. - **prompts** `MCPPrompt[]` — An optional array of pre-defined MCP prompts. - **resources** `MCPResource[]` — An optional array of pre-defined MCP resources. **Creating from a Client Instance** ```javascript import { MCPAgent } from "@aigne/core"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; // Create and configure the client manually const client = new Client({ name: "test-client", version: "1.0.0" }); const transport = new StdioClientTransport({ command: "bun", args: ["./mock-mcp-server.ts"], }); await client.connect(transport); // Create an MCPAgent from the existing client instance await using mcpAgent = MCPAgent.from({ name: client.getServerVersion()?.name, client, }); console.log('Connected to:', mcpAgent.name); ``` ## Accessing Server Capabilities Once an `MCPAgent` is connected, it exposes the server's tools, prompts, and resources through its properties. ### Accessing Skills Server-side tools are exposed as `skills` on the `MCPAgent` instance. You can access them by name and use their `invoke` method. These skills can then be passed to other agents, such as an `AIAgent`, to grant them new capabilities. **Using a Skill from an MCPAgent** ```javascript // Assuming `mcpAgent` is an initialized MCPAgent const echoSkill = mcpAgent.skills.echo; if (echoSkill) { const result = await echoSkill.invoke({ message: "Hello from AIGNE!" }); console.log(result); // Expected output: // { // "content": [ // { "text": "Tool echo: Hello from AIGNE!", "type": "text" } // ] // } } ``` ### Accessing Prompts Server-defined prompts are available under the `prompts` property. These are useful for retrieving pre-defined, complex prompt structures from the server. **Accessing a Server-Side Prompt** ```javascript // Assuming `mcpAgent` is an initialized MCPAgent const echoPrompt = mcpAgent.prompts.echo; if (echoPrompt) { const result = await echoPrompt.invoke({ message: "Hello!" }); console.log(result); // Expected output: // { // "messages": [ // { // "content": { "text": "Please process this message: Hello!", "type": "text" }, // "role": "user" // }, // ... // ] // } } ``` ### Accessing Resources Server-hosted resources or resource templates can be accessed via the `resources` property. This allows you to read data from the server by expanding a URI template. **Reading a Server-Side Resource** ```javascript // Assuming `mcpAgent` is an initialized MCPAgent const echoResource = mcpAgent.resources.echo; if (echoResource) { const result = await echoResource.invoke({ message: "Hello!" }); console.log(result); // Expected output: // { // "contents": [ // { "text": "Resource echo: Hello!", "uri": "echo://Hello!" } // ] // } } ``` ## Connection Teardown It is important to properly close the connection to the MCP server to release resources. ### Manual Shutdown You can explicitly call the `shutdown()` method. **Manually Shutting Down an Agent** ```javascript const mcpAgent = await MCPAgent.from({ url: `http://localhost:3000/mcp`, }); // ... use the agent await mcpAgent.shutdown(); ``` ### Automatic Shutdown with using For environments that support the `using` declaration (ES2023), the agent's connection will be closed automatically when it goes out of scope. This is the recommended approach for managing the agent's lifecycle. **Automatic Shutdown with 'using'** ```javascript async function connectAndUseAgent() { await using mcpAgent = await MCPAgent.from({ url: `http://localhost:3000/mcp`, }); // The agent is used here... const echo = mcpAgent.skills.echo; if (echo) await echo.invoke({ message: "Test" }); } // <-- mcpAgent.shutdown() is called automatically here. ``` ## Summary The `MCPAgent` is a crucial component for extending the AIGNE framework's capabilities by integrating with external systems. By abstracting the connection and communication logic, it allows you to treat external tools and data sources as first-class citizens in your agentic workflows. For more information on how to use the skills provided by an `MCPAgent`, see the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) documentation. --- ## Team Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/ A `TeamAgent` is a specialized agent that orchestrates a group of other agents (referred to as "skills") to perform complex tasks. It acts as a manager, directing the flow of information and coordinating the execution of its skills according to a defined strategy. This allows for the creation of sophisticated workflows where multiple specialized agents collaborate to achieve a goal that a single agent could not accomplish alone. The `TeamAgent` supports several key patterns of agent orchestration: - Sequential Execution: Agents run one after another, forming a processing pipeline. - Parallel Execution: Agents run simultaneously, and their results are merged. - Iterative Processing: The team processes each item in a list, ideal for batch operations. - Reflection: The team's output is reviewed and refined in a loop until it meets specific criteria. This component is fundamental for building modular and powerful AI systems. For details on the individual agents that can be part of a team, refer to the documentation for [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) and [Function Agent](/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/). ![Team Agent](https://media.arcblock.io/lib/85/8571815215c04fac.w1600.webp) ## Configuration A `TeamAgent` is configured with a set of options that define its behavior, execution mode, and advanced features like iteration and reflection. - **skills** `Agent[]` *(required)* — An array of agent instances that form the team. - **mode** `ProcessMode` (default: `sequential`) — The execution strategy for the agents. Can be sequential or parallel. - **reflection** `ReflectionMode` — Configuration for enabling the iterative self-correction process. - **iterateOn** `string` — The key of an input field containing an array. The team will execute once for each item in the array. - **concurrency** `number` (default: `1`) — When using iterateOn, this sets the number of items to process concurrently. - **iterateWithPreviousOutput** `boolean` (default: `false`) — If true, the output from processing one item in an iterateOn loop is merged back and made available to the next item's execution. This requires concurrency to be 1. - **includeAllStepsOutput** `boolean` (default: `false`) — In sequential mode, if true, the output from every intermediate agent is included in the final result, not just the last one. ## Execution Modes The `mode` property determines the fundamental workflow of the team. ### Sequential Mode In `sequential` mode, agents execute one by one. The output of each agent is merged with the initial input and passed to the next agent in the sequence. This creates a pipeline, suitable for tasks that require a series of transformations or steps. **team-agent-sequential.ts** ```typescript import { AIAgent, TeamAgent, ProcessMode } from "@aigne/core"; import { model } from "./model"; // Assume model is an initialized ChatModel const writerAgent = new AIAgent({ name: "writer", model, instructions: "You are a creative writer. Write a short story based on the topic: {{topic}}.", outputKey: "story", }); const editorAgent = new AIAgent({ name: "editor", model, instructions: "You are an editor. Review the following story and correct any grammatical errors: {{story}}.", outputKey: "editedStory", }); const sequentialTeam = new TeamAgent({ name: "writingTeam", mode: ProcessMode.sequential, skills: [writerAgent, editorAgent], }); // To invoke: // const result = await aigne.invoke(sequentialTeam, { topic: "a journey to the moon" }); // console.log(result.editedStory); ``` In this example, `writerAgent` first generates a `story`. The output, containing the `story` key, is then passed to `editorAgent`, which uses it to produce the final `editedStory`. ### Parallel Mode In `parallel` mode, all agents execute simultaneously with the same initial input. Their outputs are then merged into a single result. This is efficient for tasks where multiple independent pieces of information need to be generated at the same time. If multiple agents attempt to write to the same output key, the first agent to produce a value for that key "claims" it, and subsequent writes to that key from other agents are ignored. **team-agent-parallel.ts** ```typescript import { AIAgent, TeamAgent, ProcessMode } from "@aigne/core"; import { model } from "./model"; // Assume model is an initialized ChatModel const researcherAgent = new AIAgent({ name: "researcher", model, instructions: "Research the key facts about {{topic}}.", outputKey: "facts", }); const summaryAgent = new AIAgent({ name: "summarizer", model, instructions: "Provide a brief, one-paragraph summary of {{topic}}.", outputKey: "summary", }); const parallelTeam = new TeamAgent({ name: "researchTeam", mode: ProcessMode.parallel, skills: [researcherAgent, summaryAgent], }); // To invoke: // const result = await aigne.invoke(parallelTeam, { topic: "the Roman Empire" }); // console.log(result.facts); // console.log(result.summary); ``` Here, both agents start at the same time. The final result will contain both `facts` and `summary` once both agents have completed their work. ## Advanced Features ### Iteration with iterateOn The `iterateOn` property enables batch processing. You provide the name of an input key that holds an array. The `TeamAgent` will then execute its entire workflow for each item in that array. This is highly effective for processing multiple data records with the same set of agents. **team-agent-iteration.ts** ```typescript import { AIAgent, TeamAgent, ProcessMode } from "@aigne/core"; import { model } from "./model"; // Assume model is an initialized ChatModel const translatorAgent = new AIAgent({ name: "translator", model, instructions: "Translate the following text to French: {{text}}.", outputKey: "translatedText", }); const sentimentAgent = new AIAgent({ name: "sentiment", model, instructions: "Analyze the sentiment of the following text (positive, negative, or neutral): {{text}}.", outputKey: "sentiment", }); const processingTeam = new TeamAgent({ name: "batchProcessor", mode: ProcessMode.parallel, skills: [translatorAgent, sentimentAgent], iterateOn: "reviews", // The key holding the array }); const inputData = { reviews: [ { text: "This product is amazing!" }, { text: "I am very disappointed with the quality." }, { text: "It works as expected." }, ], }; // To invoke: // const result = await aigne.invoke(processingTeam, inputData); // console.log(result.reviews); /* Output would be: [ { translatedText: "Ce produit est incroyable !", sentiment: "positive" }, { translatedText: "Je suis très déçu de la qualité.", sentiment: "negative" }, { translatedText: "Cela fonctionne comme prévu.", sentiment: "neutral" } ] */ ``` ### Reflection Reflection provides a mechanism for self-correction and quality assurance. When configured, a `TeamAgent`'s output is passed to a designated `reviewer` agent. The reviewer assesses the output against certain criteria. If the output is not "approved," the entire process runs again, feeding the previous output and the reviewer's feedback into the next iteration. This loop continues until the output is approved or a `maxIterations` limit is reached. The configuration for reflection is provided under the `reflection` key. - **reviewer** `Agent` *(required)* — The agent responsible for evaluating the team's output. - **isApproved** `string | Function` *(required)* — A condition for approval. If a string, it's the name of a boolean field in the reviewer's output. If a function, it receives the reviewer's output and must return a truthy value for approval. - **maxIterations** `number` (default: `3`) — The maximum number of review-refine cycles before failing. - **returnLastOnMaxIterations** `boolean` (default: `false`) — If true, the process returns the last generated output upon hitting maxIterations instead of throwing an error. - **customErrorMessage** `string` — A custom error message to throw when max iterations are reached without approval. **team-agent-reflection.ts** ```typescript import { AIAgent, TeamAgent } from "@aigne/core"; import { model } from "./model"; // Assume model is an initialized ChatModel const planGenerator = new AIAgent({ name: "planGenerator", model, instructions: `Generate a 3-step marketing plan for a new {{product}}. If you received feedback, incorporate it. Feedback: {{feedback}}`, outputKey: "plan", }); const planReviewer = new AIAgent({ name: "planReviewer", model, instructions: `Review the marketing plan: {{plan}}. Does it include a budget allocation? If not, provide feedback to add one. Output JSON with an 'approved' (boolean) and 'feedback' (string) field.`, output: { json: { schema: { type: "object", properties: { approved: { type: "boolean" }, feedback: { type: "string" }, }, }, }, }, }); const reflectionTeam = new TeamAgent({ name: "planningTeam", skills: [planGenerator], reflection: { reviewer: planReviewer, isApproved: "approved", // Check the 'approved' field in the reviewer's output maxIterations: 3, }, }); // To invoke: // const result = await aigne.invoke(reflectionTeam, { product: "smart watch" }); // console.log(result.plan); ``` In this flow, `planGenerator` creates an initial plan. `planReviewer` checks it. If no budget is mentioned, it sets `approved` to `false` and provides feedback. The `TeamAgent` then re-runs `planGenerator`, this time including the feedback, until the plan is approved. ## YAML Definition You can also define a `TeamAgent` declaratively using YAML. **team-agent-definition.yaml** ```yaml type: team name: test-team-agent description: Test team agent skills: - sandbox.js # Path to another agent definition - chat.yaml mode: parallel iterate_on: sections concurrency: 2 include-all-steps-output: true reflection: reviewer: team-agent-reviewer.yaml is_approved: approved max_iterations: 5 return_last_on_max_iterations: true ``` This YAML defines a parallel team that iterates over an input field named `sections` and also includes a reflection step for quality control. ## Summary The `TeamAgent` is a powerful tool for orchestrating multiple agents to solve complex problems. By combining agents in `sequential` or `parallel` workflows and leveraging advanced features like `iterateOn` for batch processing and `reflection` for self-correction, you can build robust and sophisticated AI applications. To learn more about the building blocks of a team, see the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) and [Function Agent](/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/) documentation. --- ## Transform Agent URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-agents-transform-agent-9dc03e/ The `TransformAgent` is a specialized agent that provides a declarative way to transform structured data using [JSONata](https://jsonata.org/) expressions. It is ideal for scenarios where data needs to be mapped, restructured, or converted from one format to another without requiring complex imperative logic. Common use cases include: - Normalizing API responses to a consistent format. - Mapping fields between different data schemas (e.g., database results to an application model). - Restructuring configuration data. - Converting data formats, such as changing field names from `snake_case` to `camelCase`. - Performing simple aggregations, calculations, or filtering on data. The following diagram illustrates the workflow of the Transform Agent, showing how a developer defines a transformation, provides input data, and receives the transformed output. ![Transform Agent](https://media.arcblock.io/lib/06/06f2d2b47dee4a66.w1600.webp) For transformations that require more complex, custom logic, consider using the [Function Agent](/en/docs/aigne-framework/developer-guide-agents-function-agent-9dc03e/). ## Configuration The `TransformAgent` is configured using the following options. - **jsonata** `string` *(required)* — A JSONata expression string that defines the data transformation logic. JSONata is a lightweight query and transformation language for JSON data. The expression dictates how the input message is transformed into the output message. You can experiment with expressions in the JSONata Playground. ``` **Common Patterns:** - **Field Mapping:** `{ "newField": oldField }` - **Array Transformation:** `items.{ "name": product_name, "price": price }` - **Calculations:** `$sum(items.price)` - **Conditional Logic:** `condition ? value1 : value2` - **String Operations:** `$uppercase(name)` ``` ## Usage The `TransformAgent` can be defined either programmatically using TypeScript or declaratively using YAML. ### TypeScript Example This example demonstrates how to create a `TransformAgent` that converts field names from snake_case to camelCase. **Transform Agent Example** ```typescript import { TransformAgent } from "@aigne/core"; // 1. Define the TransformAgent const snakeToCamelAgent = TransformAgent.from({ name: "snake-to-camel-converter", description: "Converts user data fields from snake_case to camelCase.", jsonata: `{ "userId": user_id, "userName": user_name, "createdAt": created_at }`, }); // 2. Define the input data const inputData = { user_id: "usr_12345", user_name: "John Doe", created_at: "2023-10-27T10:00:00Z", }; // 3. Invoke the agent to perform the transformation async function runTransform() { const result = await snakeToCamelAgent.invoke(inputData); console.log(result); } runTransform(); ``` The agent applies the JSONata expression to the `inputData`, renaming the keys as specified. Output ```json { "userId": "usr_12345", "userName": "John Doe", "createdAt": "2023-10-27T10:00:00Z" } ``` ### YAML Example The same agent can be defined declaratively in a YAML file. This is useful for defining agents as part of a larger configuration. **transform.yaml** ```yaml type: transform name: transform-agent description: | A Transform Agent that processes input data using JSONata expressions. input_schema: type: object properties: user_id: type: string description: The ID of the user. user_name: type: string description: The name of the user. created_at: type: string description: The creation date of the user. required: - user_id - user_name - created_at output_schema: type: object properties: userId: type: string description: The ID of the user. userName: type: string description: The name of the user. createdAt: type: string description: The creation date of the user. required: - userId - userName - createdAt jsonata: | { "userId": user_id, "userName": user_name, "createdAt": created_at } ``` This YAML definition specifies the agent's type, name, schemas, and the core `jsonata` transformation expression, achieving the same result as the TypeScript example. ## Summary The `TransformAgent` offers a powerful and concise method for handling structured data transformations. By leveraging JSONata, it separates data mapping and restructuring logic from your main application code, leading to cleaner and more maintainable agentic workflows. For orchestrating this agent with others, see the [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/) documentation. --- ## Core Concepts URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-core-concepts-9dc03e/ To effectively build applications with the AIGNE Framework, it is essential to first understand its fundamental architectural components. This section provides a high-level overview of the primary building blocks and their interactions. A clear grasp of these concepts will facilitate a more intuitive development process. The framework is designed around a few key abstractions that work together to orchestrate complex AI-driven workflows. The main components are the AIGNE orchestrator, the Agent as the basic unit of work, Models for interfacing with AI services, and Memory for state persistence. The following diagram illustrates the relationship between these core components. ![Core Concepts](https://media.arcblock.io/lib/35/3555c9a4ae094393.w1600.webp) ## Architectural Building Blocks The AIGNE Framework is composed of four primary concepts. Understanding each one is crucial for building robust and scalable agent-based applications. ::::card-group ::link-card{title="AIGNE" description="The central orchestrator responsible for managing the lifecycle of agents, coordinating their interactions, and handling the overall execution flow." icon="box" href="/en/docs/aigne-framework/developer-guide-core-concepts-aigne-engine-9dc03e/"} ::link-card{title="Agents" description="The fundamental unit of work. An Agent is an abstraction that encapsulates a specific capability, from running a simple function to complex reasoning." icon="bot" href="/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/"} ::link-card{title="Models" description="Specialized agents that provide a standardized interface to external services, such as Large Language Models (LLMs) or image generation APIs." icon="brain" href="/en/docs/aigne-framework/developer-guide-core-concepts-models-9dc03e/"} ::link-card{title="Memory" description="Provides agents with the ability to persist and recall information, enabling stateful conversations and context-aware behavior over time." icon="database" href="/en/docs/aigne-framework/developer-guide-core-concepts-memory-9dc03e/"} :::: ## Summary This section has introduced the four foundational pillars of the AIGNE Framework: the `AIGNE` orchestrator, the `Agent`, `Models`, and `Memory`. Each component plays a distinct and vital role in the architecture. For a more comprehensive understanding, it is recommended to proceed to the detailed documentation for each concept. - Next: Dive deeper into the [AIGNE orchestrator](/en/docs/aigne-framework/developer-guide-core-concepts-aigne-engine-9dc03e/). --- ## Agents URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/ In the AIGNE Framework, the `Agent` is the fundamental unit of work. It is an abstract class that establishes a standard contract for all specialized agent types. An agent can be conceptualized as a distinct worker capable of executing a specific task, processing information, and interacting with other agents within the system. Every specialized agent, whether designed for interacting with an AI model, transforming data, or orchestrating a team of other agents, inherits its core structure and behavior from this base `Agent` class. This architectural principle ensures consistency and predictability across the framework. Further reading on specialized agent types can be found in the [Agent Types](/en/docs/aigne-framework/developer-guide-agents-9dc03e/) section. ## Core Concepts The `Agent` class is designed around several core concepts that define its identity, data contracts, and operational behavior. These are configured via the `AgentOptions` object during the agent's instantiation. ### Key Properties The following properties define an agent's configuration: | Property | Type | Description | |---|---|---| | `name` | `string` | A unique identifier for the agent, used for logging and referencing. It defaults to the constructor's class name if not specified. | | `description` | `string` | A human-readable summary of the agent's purpose and capabilities, useful for documentation and debugging. | | `inputSchema` | `ZodType` | A Zod schema defining the structure and validation rules for the agent's input data. This ensures data integrity. | | `outputSchema` | `ZodType` | A Zod schema defining the structure and validation rules for the agent's output data. | | `skills` | `Agent[]` | A list of other agents that this agent can invoke to perform delegated sub-tasks, enabling compositional behavior. | | `memory` | `MemoryAgent` | An optional memory unit allowing the agent to persist and recall state across multiple interactions. | | `hooks` | `AgentHooks[]` | A set of lifecycle hooks (e.g., `onStart`, `onEnd`) for observing or modifying agent behavior at runtime. | | `guideRails` | `GuideRailAgent[]` | A list of specialized agents that enforce rules, policies, or constraints on the agent's inputs and outputs. | ### The process Method The `process` method is the central component of every agent. It is defined as an `abstract` method in the base `Agent` class, which mandates that any concrete agent class must provide an implementation. This method contains the core logic that defines what the agent does. The method receives the validated input message and invocation options, including the execution `Context`, and is responsible for producing an output. **Agent.ts** ```typescript export abstract class Agent { // ... constructor and other properties /** * Core processing method of the agent, must be implemented in subclasses * * @param input Input message * @param options Options for agent invocation * @returns Processing result */ abstract process(input: I, options: AgentInvokeOptions): PromiseOrValue>; // ... other methods } ``` The return value, `AgentProcessResult`, can be a direct object, a streaming response, an async generator, or another agent instance for task forwarding. ## Agent Lifecycle The execution of an agent adheres to a structured lifecycle, which provides clear points for extension via hooks. ![Agents](https://media.arcblock.io/lib/7d/7dab44a0402c2fe2.w1600.webp) ::::steps :::step{title="Invocation"} An agent's execution is initiated by calling its `invoke()` method with an input payload. ::: :::step{title="`onStart`"} Hook: The `onStart` hooks are triggered, providing an opportunity for pre-processing logic, such as logging or input transformation. ::: :::step{title="Input Validation"} The input data is automatically validated against the agent's `inputSchema`. If validation fails, the process is aborted. ::: :::step{title="`process()`"} Execution: The core logic defined in the agent's `process()` method is executed. ::: :::step{title="Output Validation"} The result from the `process()` method is validated against the agent's `outputSchema`. ::: :::step{title="`onEnd`"} Hook: The `onEnd` hooks are triggered with the final output or any error that occurred. This is the designated point for post-processing, logging results, or implementing custom failure handling. ::: :::step{title="Return Value"} The final, validated output is returned to the original caller. ::: :::: This systematic lifecycle ensures that data is consistently validated and offers clear, non-invasive extension points for custom logic. ## Implementation Example To create a functional agent, extend the base `Agent` class and implement the `process` method. The following example defines an agent that accepts two numbers and returns their sum. **adder-agent.ts** ```typescript import { Agent, type AgentInvokeOptions, type Message } from "@aigne/core"; import { z } from "zod"; // 1. Define the input and output schemas using Zod for validation. const inputSchema = z.object({ a: z.number(), b: z.number(), }); const outputSchema = z.object({ sum: z.number(), }); // 2. Infer TypeScript types from the Zod schemas. type AddAgentInput = z.infer; type AddAgentOutput = z.infer; // 3. Create the custom agent class by extending Agent. export class AddAgent extends Agent { constructor() { super({ name: "AddAgent", description: "An agent that adds two numbers.", inputSchema, outputSchema, }); } // 4. Implement the core logic in the process method. async process(input: AddAgentInput, options: AgentInvokeOptions): Promise { const { a, b } = input; const sum = a + b; return { sum }; } } ``` This example illustrates the standard implementation pattern: 1. Define Zod schemas for input and output data structures. 2. Extend the `Agent` class with the corresponding input and output types. 3. Provide the schemas and other metadata to the `super()` constructor. 4. Implement the agent's specific logic within the `process` method. ## Summary The `Agent` class is the foundational abstraction in the AIGNE Framework. It provides a consistent and robust contract for all operational units, ensuring they are identifiable, adhere to clear data schemas, and follow a predictable execution lifecycle. By abstracting this common machinery, the framework allows developers to focus exclusively on implementing the unique logic required for their tasks within the `process` method. For details on how agents are executed and managed by the central engine, refer to the [AIGNE](/en/docs/aigne-framework/developer-guide-core-concepts-aigne-engine-9dc03e/) documentation. To explore the various specialized agent implementations available, see the [Agent Types](/en/docs/aigne-framework/developer-guide-agents-9dc03e/) section. --- ## AIGNE URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-core-concepts-aigne-engine-9dc03e/ The `AIGNE` class is the central execution engine of the framework. It orchestrates multiple agents to build complex AI applications, serving as the main coordination point for agent interactions, message passing, and the overall execution flow. This guide covers how to instantiate and configure the `AIGNE` engine, execute agents using the `invoke` method, and manage the application lifecycle. ![AIGNE](https://media.arcblock.io/lib/13/133f4d00259fd636.w1600.webp) ## Overview AIGNE acts as the container for your entire agentic application. Its primary responsibilities include: - Agent Management: Manages the lifecycle of all registered agents and skills. - Model Configuration: Provides a global default configuration for chat and image models, which can be inherited or overridden by individual agents. - Execution Context: Creates and manages isolated contexts for each invocation, ensuring that concurrent operations do not interfere with each other. - Lifecycle Control: Offers methods to gracefully start and stop the application, ensuring all resources are properly handled. ## Instantiation There are two primary ways to create an `AIGNE` instance: programmatically using the constructor or by loading a configuration from a directory. ### Using the Constructor The most direct method is to use the `AIGNE` constructor, passing in an options object. This approach is ideal for applications where configuration is managed dynamically in code. **Instantiating AIGNE** ```typescript import { AIGNE } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/openai"; const aigne = new AIGNE({ name: "MyFirstAIGNEApp", model: new OpenAIChatModel({ apiKey: process.env.OPENAI_API_KEY, model: "gpt-4o-mini", }), }); ``` ### Loading from Configuration For more complex projects, it is best practice to define your application structure in a directory containing an `aigne.yaml` file and other agent definitions. The static `AIGNE.load()` method reads this directory and constructs a fully configured instance. This promotes separation of configuration from logic. **Loading AIGNE from a Directory** ```typescript import { AIGNE } from "@aigne/core"; import { join } from "node:path"; const configPath = join(process.cwd(), "my-aigne-project"); const aigne = await AIGNE.load(configPath); ``` ## Configuration Options The `AIGNE` constructor accepts an `AIGNEOptions` object to control its behavior. - **name** `string` — A unique name for the AIGNE instance. - **description** `string` — A brief description of the instance's purpose. - **rootDir** `string` — The root directory for resolving relative paths for agents and skills. - **model** `ChatModel` — A global default chat model for all agents that do not specify their own. See Models for more details. - **imageModel** `ImageModel` — A global default image model for image generation tasks. - **agents** `Agent[]` — An array of agent instances to register with the engine upon initialization. - **skills** `Agent[]` — An array of skill agents to make available to other agents. - **limits** `ContextLimits` — Execution limits, such as timeouts or maximum tokens, to apply to all invocations. - **observer** `AIGNEObserver` — An observer instance for monitoring and logging execution traces. ## Agent and Lifecycle Management Once an instance is created, you can manage agents and control the application lifecycle. ### Adding Agents While agents can be provided in the constructor, you can also add them dynamically using the `addAgent` method. Each agent is attached to the AIGNE instance, giving it access to shared resources like the global model. **Dynamically Adding an Agent** ```typescript import { AIAgent } from "@aigne/core"; import { AIGNE } from "@aigne/core"; // Assuming 'aigne' is an existing AIGNE instance const aigne = new AIGNE(); const myAgent = new AIAgent({ instructions: "You are a helpful assistant.", }); aigne.addAgent(myAgent); ``` ### Shutting Down To ensure a clean exit and proper resource cleanup, call the `shutdown` method. This is crucial for long-running applications to prevent resource leaks. The engine also automatically handles process exit signals like `SIGINT`. **Graceful Shutdown** ```typescript // Assuming 'aigne' is an existing AIGNE instance await aigne.shutdown(); ``` ## Invoking Agents The `invoke` method is the primary entry point for executing an agent. It is an overloaded method that supports several patterns, from simple request-response to real-time streaming. ### Standard Invocation The most common use case is to provide an agent and an input message. This returns a promise that resolves with the agent's final output. **Standard Agent Invocation** ```typescript // Assuming 'aigne' and 'myAgent' are configured const result = await aigne.invoke(myAgent, { message: "What is the AIGNE Framework?", }); console.log(result.message); // Expected output: A descriptive answer about the framework. ``` ### Streaming Responses For interactive applications like chatbots, you can enable streaming to receive the response incrementally. Setting `streaming: true` in the options returns an `AgentResponseStream`. You can then iterate over the stream to process chunks of data as they arrive. **Streaming Agent Responses** ```typescript import { isAgentResponseDelta } from "@aigne/core"; // Assuming 'aigne' and 'myAgent' are configured const stream = await aigne.invoke( myAgent, { message: "Tell me a short story." }, { streaming: true } ); let fullResponse = ""; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const textDelta = chunk.delta.text?.message ?? ""; fullResponse += textDelta; process.stdout.write(textDelta); } } console.log("\n--- End of Story ---"); ``` ### Creating a User Agent Invoking an agent without a message creates a `UserAgent`. This is a stateful wrapper that preserves the conversation context across multiple calls, making it ideal for building conversational experiences. **Creating a Stateful UserAgent** ```typescript // Assuming 'aigne' and 'myAgent' are configured // Create a UserAgent to maintain context const userAgent = aigne.invoke(myAgent); // First interaction const response1 = await userAgent.invoke({ message: "My name is Bob." }); console.log(response1.message); // e.g., "Nice to meet you, Bob!" // Second interaction preserves context const response2 = await userAgent.invoke({ message: "What is my name?" }); console.log(response2.message); // e.g., "Your name is Bob." ``` The `invoke` method offers additional overloads for advanced scenarios, such as returning the final active agent in a multi-agent team. Refer to the API reference for a complete list of signatures. With a clear understanding of the `AIGNE` engine, you are now prepared to explore the different types of [Agents](/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/) that form the building blocks of your application. --- ## Memory URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-core-concepts-memory-9dc03e/ The `MemoryAgent` provides a mechanism for agents to maintain state and remember information across interactions. It acts as a specialized orchestrator that does not process messages directly but manages memory operations through two key components: a `Recorder` for storing information and a `Retriever` for recalling it. This separation of concerns allows for flexible and pluggable memory storage solutions. ## Core Components The memory system is comprised of three main classes: ::::steps :::step{title="`MemoryAgent`"} The central agent that manages memory operations. It is configured with a recorder and a retriever and provides `record()` and `retrieve()` methods to interact with the memory store. ::: :::step{title="`MemoryRecorder`"} An agent responsible for writing information to a persistent storage backend (e.g., a database, file system, or vector store). You must provide the implementation for how and where the data is stored. ::: :::step{title="`MemoryRetriever`"} An agent responsible for fetching information from the storage backend based on specified criteria, such as a search query or a limit. You must provide the implementation for the retrieval logic. ::: :::: ![Memory](https://media.arcblock.io/lib/9a/9a0388c78736bd3f.w1600.webp) ## How It Works The `MemoryAgent` delegates tasks to its subordinate agents. When you call the `record()` method on a `MemoryAgent`, it invokes its configured `MemoryRecorder` to persist the data. Similarly, when you call `retrieve()`, it invokes the `MemoryRetriever` to query and return the stored information. This architecture allows developers to define custom storage and retrieval logic without altering the core agent workflows. For example, you can implement a recorder that saves conversation history to a PostgreSQL database and a retriever that uses vector embeddings to find semantically similar past interactions. ## MemoryAgent The `MemoryAgent` is the primary interface for memory management. It is not designed to be called directly within a chain of processing agents but rather as a stateful service available to other agents or your application logic. ### Configuration To create a `MemoryAgent`, you provide it with a `recorder` and a `retriever`. These can be instances of `MemoryRecorder` and `MemoryRetriever` or function definitions for their respective `process` methods. **Agent Initialization** ```typescript import { MemoryAgent, MemoryRecorder, MemoryRetriever } from "@aigne/core"; import { v7 as uuidv7 } from "@aigne/uuid"; // 1. Define a simple in-memory store for demonstration const memoryStore: Map = new Map(); // 2. Implement the recorder logic const recorder = new MemoryRecorder({ async process({ content }) { const memories = content.map((item) => { const memory = { id: uuidv7(), content: item, createdAt: new Date().toISOString(), }; memoryStore.set(memory.id, memory); return memory; }); return { memories }; }, }); // 3. Implement the retriever logic const retriever = new MemoryRetriever({ async process({ search, limit = 10 }) { // This is a simplistic search. A real implementation might use a database query or vector search. const allMemories = Array.from(memoryStore.values()); const filteredMemories = search ? allMemories.filter((m) => JSON.stringify(m.content).includes(search as string)) : allMemories; return { memories: filteredMemories.slice(0, limit) }; }, }); // 4. Instantiate the MemoryAgent const memoryAgent = new MemoryAgent({ recorder, retriever, }); ``` The example above demonstrates creating a `MemoryAgent` with a simple in-memory storage mechanism. In a production environment, you would replace this with a more robust solution like a database. ### MemoryAgentOptions - **recorder** `MemoryRecorder | MemoryRecorderOptions['process'] | MemoryRecorderOptions` — The agent or function responsible for storing memories. It can be a full MemoryRecorder instance, a configuration object, or just the processing function. - **retriever** `MemoryRetriever | MemoryRetrieverOptions['process'] | MemoryRetrieverOptions` — The agent or function responsible for retrieving memories. It can be a full MemoryRetriever instance, a configuration object, or just the processing function. - **autoUpdate** `boolean` — If true, the agent will automatically record information after completing operations to create a history of interactions. - **subscribeTopic** `string | string[]` — The topic(s) to subscribe to for automatic message recording. - **skills** `Agent[]` — An array of other agents to be available as skills. The recorder and retriever are automatically added to this list. ## MemoryRecorder The `MemoryRecorder` is an abstract agent class that defines the contract for storing memories. You must provide a concrete implementation of its `process` method. ### MemoryRecorderInput The `process` method of a `MemoryRecorder` receives a `MemoryRecorderInput` object. - **content** `array` *(required)* — An array of objects to be stored as memories. Each object can contain an input, output, and source to contextualize the memory. - **input** `Message` — The input message that led to this memory (e.g., a user's prompt). - **output** `Message` — The output message generated (e.g., an AI's response). - **source** `string` — The identifier of the agent or system that produced the output. ### MemoryRecorderOutput The `process` method must return a `MemoryRecorderOutput` object. - **memories** `Memory[]` *(required)* — An array of the newly created memory objects, each including its unique ID, the original content, and a creation timestamp. ## MemoryRetriever The `MemoryRetriever` is an abstract agent class that defines the contract for fetching memories from storage. You must provide a concrete implementation of its `process` method. ### MemoryRetrieverInput The `process` method of a `MemoryRetriever` receives a `MemoryRetrieverInput` object to filter and limit the results. - **limit** `number` — The maximum number of memories to return. Useful for pagination or keeping context windows small. - **search** `string | Message` — A search term or message object to filter memories. The implementation determines how this value is used (e.g., keyword search, vector similarity). ### MemoryRetrieverOutput The `process` method must return a `MemoryRetrieverOutput` object. - **memories** `Memory[]` *(required)* — An array of the memory objects that matched the retrieval criteria. ## Usage Example Once the `MemoryAgent` is configured, you can use it within your application's context to record and retrieve information. **AIGNE Interaction** ```typescript import { AIGNE } from "@aigne/core"; // Assuming memoryAgent is configured as shown in the first example const aigne = new AIGNE({ // ...other configurations }); async function run() { // Record a new memory const recordedMemory = await aigne.invoke(memoryAgent.record.bind(memoryAgent), { content: [{ input: { query: "What is the capital of France?" } }], }); console.log("Recorded:", recordedMemory.memories[0].id); // Retrieve memories const retrievedMemories = await aigne.invoke(memoryAgent.retrieve.bind(memoryAgent), { search: "France", limit: 5, }); console.log("Retrieved:", retrievedMemories.memories); } run(); ``` This example shows how to use the `aigne.invoke` method to call the `record` and `retrieve` functions on the `memoryAgent` instance, effectively managing the agent's state across interactions. ## Summary The `MemoryAgent` provides a powerful and flexible abstraction for managing state in agentic applications. By separating the orchestration (`MemoryAgent`) from the implementation details (`MemoryRecorder`, `MemoryRetriever`), you can easily integrate various storage backends, from simple in-memory arrays to sophisticated vector databases. For more information on the core execution engine, see the [AIGNE](/en/docs/aigne-framework/developer-guide-core-concepts-aigne-engine-9dc03e/) documentation. To understand the fundamental building block of work, refer to the [Agents](/en/docs/aigne-framework/developer-guide-core-concepts-agents-9dc03e/) page. --- ## Models URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-core-concepts-models-9dc03e/ Models are specialized agents that serve as a crucial abstraction layer, providing a standardized interface for interacting with external AI services, such as Large Language Models (LLMs) and image generation platforms. They encapsulate the complexity of API communication, allowing developers to work with various AI providers through a consistent and unified contract. The AIGNE Framework defines a base `Model` class, which is extended by two primary specializations: `ChatModel` for text-based conversational AI and `ImageModel` for image generation tasks. These abstractions are the foundation upon which higher-level agents like `AIAgent` and `ImageAgent` are built. ## Core Concepts The `Model` layer is designed to streamline interactions with different AI providers. Instead of writing provider-specific code for each service (like OpenAI, Anthropic, or Google Gemini), you interact with the standardized `ChatModel` or `ImageModel` interface. The AIGNE framework, through specific model packages (e.g., `@aigne/openai`), handles the translation between this standard format and the provider's native API. This design offers several key advantages: - Provider Agnostic: Swap out underlying AI models with minimal code changes. For example, you can switch from OpenAI's GPT-4 to Anthropic's Claude 3 by simply changing the model instantiation. - Standardized Data Structures: All models use consistent input and output schemas (`ChatModelInput`, `ImageModelOutput`, etc.), simplifying data handling and agent composition. - Simplified API: The models provide a clean, high-level API that abstracts away the nuances of authentication, request formatting, and error handling for each external service. The following diagram illustrates the relationship between the base `Agent`, the `Model` abstractions, and the external AI services they connect to. ![Models](https://media.arcblock.io/lib/c3/c32d0965b2db8925.w1600.webp) ## ChatModel Abstraction The `ChatModel` is an abstract class designed for interfacing with Large Language Models (LLMs). It provides a structured way to handle conversational interactions, including multi-turn dialogues, tool usage, and structured data extraction. ### ChatModelInput The `ChatModelInput` interface defines the data structure for requests sent to a language model. It standardizes how messages, tools, and other configurations are passed. - **messages** `ChatModelInputMessage[]` *(required)* — An array of message objects that form the conversation history and the current prompt. - **responseFormat** `ChatModelInputResponseFormat` — Specifies the desired format for the model's output, such as plain text or structured JSON based on a provided schema. - **tools** `ChatModelInputTool[]` — A list of available tools (functions) that the model can request to call to perform actions or retrieve information. - **toolChoice** `ChatModelInputToolChoice` — Controls how the model uses the provided tools. It can be set to "auto", "none", "required", or to force a specific function call. - **modelOptions** `ChatModelInputOptions` — A container for provider-specific options, such as temperature, topP, or parallelToolCalls. - **outputFileType** `'local' | 'file'` — Specifies the desired format for any file-based outputs, either as a local file path (local) or a base64-encoded string (file). #### ChatModelInputMessage Each message in the `messages` array follows a defined structure. - **role** `'system' | 'user' | 'agent' | 'tool'` *(required)* — The role of the message sender. system provides instructions, user represents user input, agent is for model responses, and tool is for the output of a tool call. - **content** `string | UnionContent[]` — The content of the message. It can be a simple string or an array for multimodal content, combining text and images (FileUnionContent). - **toolCalls** `object[]` — Used in an agent message to indicate one or more tool calls initiated by the model. - **toolCallId** `string` — Used in a tool message to link the tool's output back to the corresponding toolCalls request. ### ChatModelOutput The `ChatModelOutput` interface standardizes the response received from a language model. - **text** `string` — The text-based content of the model's response. - **json** `object` — The JSON object returned by the model when responseFormat is set to "json_schema". - **toolCalls** `ChatModelOutputToolCall[]` — An array of tool call requests made by the model. Each object includes the function name and arguments. - **usage** `ChatModelOutputUsage` — An object containing token usage statistics, including inputTokens and outputTokens. - **model** `string` — The identifier of the model that generated the response. - **files** `FileUnionContent[]` — An array of files generated by the model, if any. ## ImageModel Abstraction The `ImageModel` is an abstract class for interfacing with image generation models. It provides a simplified contract for creating or editing images based on textual prompts. ### ImageModelInput The `ImageModelInput` interface defines the request structure for an image generation task. - **prompt** `string` *(required)* — A textual description of the desired image. - **image** `FileUnionContent[]` — An optional array of input images, used for tasks like image editing or creating variations. - **n** `number` — The number of images to generate. Defaults to 1. - **outputFileType** `'local' | 'file'` — Specifies whether the output images should be saved as local files (local) or returned as base64-encoded strings (file). - **modelOptions** `ImageModelInputOptions` — A container for provider-specific options, such as image dimensions, quality, or style presets. ### ImageModelOutput The `ImageModelOutput` interface defines the response structure from an image generation service. - **images** `FileUnionContent[]` *(required)* — An array of the generated images. The format of each element depends on the outputFileType specified in the input. - **usage** `ChatModelOutputUsage` — An object containing usage statistics, which may include token counts or other provider-specific metrics. - **model** `string` — The identifier of the model that generated the images. ## File Content Types Models handle various forms of file inputs for multimodal tasks through the `FileUnionContent` type. This discriminated union allows files to be represented in three ways: - `LocalContent`: Represents a file stored on the local filesystem. - - `type`: "local" - `path`: The absolute path to the file. - `UrlContent`: Represents a file accessible via a public URL. - - `type`: "url" - `url`: The URL of the file. - `FileContent`: Represents a file as a base64-encoded string. - - `type`: "file" - `data`: The base64-encoded content of the file. The `Model` base class includes a `transformFileType` method that can automatically convert between these formats as needed, simplifying file handling across different agents and model providers. ## Summary The `ChatModel` and `ImageModel` abstractions are core components that make the AIGNE Framework flexible and provider-agnostic. They provide a stable, standardized interface for interacting with a wide range of external AI services. - To learn how to use these models in practice, see the documentation for the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) and [Image Agent](/en/docs/aigne-framework/developer-guide-agents-image-agent-9dc03e/). - For details on configuring specific providers like OpenAI, Anthropic, or Google Gemini, refer to the guides in the [Models](/en/docs/aigne-framework/models-9dc03e/) section. --- ## Getting Started URL: https://www.arcblock.io/en/docs/aigne-framework/developer-guide-getting-started-9dc03e/ This guide provides the necessary steps to set up your development environment and run your first AI agent using the AIGNE Framework. The process is designed to be completed in under 30 minutes, offering a practical, hands-on introduction to the framework's fundamental workflow. We will cover system prerequisites, installation of the required packages, and a complete, copy-paste-ready example that demonstrates how to define, configure, and execute a basic AI agent. ## Prerequisites Before proceeding, ensure your development environment meets the following requirement: - Node.js: Version 20.0 or higher is required. You can verify your Node.js version by executing the following command in your terminal: ```bash node -v ``` ## Installation To begin, you need to install the core AIGNE package and a model provider package. For this guide, we will use the official OpenAI model provider. Install the necessary packages using your preferred package manager: ::::card-group ::link-card{title="npm" description="```bash npm install @aigne/core @aigne/openai ```" icon="package"} ::link-card{title="yarn" description="```bash yarn add @aigne/core @aigne/openai ```" icon="package"} ::link-card{title="pnpm" description="```bash pnpm add @aigne/core @aigne/openai ```" icon="package"} :::: Additionally, you will need an OpenAI API key. Set it as an environment variable named `OPENAI_API_KEY`. **.env** ```bash OPENAI_API_KEY="sk-..." ``` ## Quick Start Example This example demonstrates the complete process of creating and running a simple "assistant" agent. 1. Create a new TypeScript file named `index.ts`. 2. Copy and paste the following code into the file. **index.ts** ```typescript import { AIAgent, AIGNE } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/openai"; // 1. Instantiate the AI Model // This creates a connection to the OpenAI API using the specified model. // The API key is read from the OPENAI_API_KEY environment variable. const model = new OpenAIChatModel({ model: "gpt-4o-mini", }); // 2. Define the AI Agent // An agent is a unit of work. This AIAgent is configured with // instructions that define its personality and task. const assistantAgent = AIAgent.from({ name: "Assistant", instructions: "You are a helpful and friendly assistant.", }); // 3. Instantiate the AIGNE // The AIGNE class is the central orchestrator that manages and runs agents. // It is configured with the model that its agents will use. const aigne = new AIGNE({ model }); async function main() { // 4. Invoke the Agent // The invoke method runs the agent with a given input. // The framework handles the interaction with the model. const response = await aigne.invoke( assistantAgent, "Why is the sky blue?" ); // 5. Print the Response console.log(response); } main(); ``` ### Running the Example Execute the script from your terminal. If you are using TypeScript, you can use a tool like `ts-node`. ```bash npx ts-node index.ts ``` ### Expected Output The output will be the agent's response to the question, formatted as a JSON object. The content of the `message` field will vary, as it is generated by the AI model. ```json { "message": "The sky appears blue because of a phenomenon called Rayleigh scattering..." } ``` ## Code Breakdown The example is composed of four primary steps that represent the core workflow of the AIGNE Framework. ::::steps :::step{title="Model Initialization"} An instance of `OpenAIChatModel` is created. This object serves as a direct interface to the specified OpenAI model (e.g., `gpt-4o-mini`). It requires an API key for authentication, which is automatically sourced from the `OPENAI_API_KEY` environment variable. ::: :::step{title="Agent Definition"} An `AIAgent` is defined using the static `from` method. This is the fundamental unit of work in the framework. Its behavior is defined by the `instructions` property, which acts as a system prompt, guiding the AI model's responses. ::: :::step{title="AIGNE Instantiation"} The `AIGNE` class is instantiated. It acts as the execution engine and orchestrator for all agents. By passing the `model` instance into its constructor, we establish a default model for all agents managed by this AIGNE instance. ::: :::step{title="Agent Invocation"} The `aigne.invoke()` method is called to execute the `assistantAgent`. The first argument is the agent to run, and the second is the input message. The framework manages the complete lifecycle of the request: sending the prompt and instructions to the model, receiving the response, and returning it as structured output. ::: :::: This simple example illustrates the modular and declarative nature of the framework, where models, agents, and the execution engine are configured and composed to build powerful AI-driven applications. ## Summary In this guide, you have successfully set up your environment, installed the necessary AIGNE packages, and built and run a functional AI agent. You have learned the basic workflow: defining a model, creating an agent with specific instructions, and using the AIGNE to invoke it with a user prompt. With this foundation, you are now ready to explore more advanced topics. - To understand the fundamental building blocks of the framework in greater detail, proceed to the [Core Concepts](/en/docs/aigne-framework/developer-guide-core-concepts-9dc03e/) documentation. - To learn about the different types of specialized agents and their use cases, see the [Agent Types](/en/docs/aigne-framework/developer-guide-agents-9dc03e/) section. --- ## Examples URL: https://www.arcblock.io/en/docs/aigne-framework/examples-9dc03e/ Explore a collection of practical examples that demonstrate the various features and workflow patterns of the AIGNE Framework. This section provides hands-on, executable demos to help you understand intelligent conversation, MCP protocol integration, memory mechanisms, and complex agentic workflows. ## Quick Start You can run any example directly without a local installation using `npx`. This approach is the fastest way to see the AIGNE Framework in action. ### Prerequisites - Node.js (version 20.0 or higher) and npm installed. - An API key for your chosen Large Language Model (LLM) provider (e.g., OpenAI). ### Run an Example Execute the following commands in your terminal to run a basic chatbot. 1. Set your API key: Replace `YOUR_OPENAI_API_KEY` with your actual OpenAI API key. ```sh export OPENAI_API_KEY=YOUR_OPENAI_API_KEY ``` 2. Run in one-shot mode: The agent will process a default prompt and exit. ```sh npx -y @aigne/example-chat-bot ``` 3. Run in interactive mode: Use the `--interactive` flag to start an interactive session where you can have a conversation with the agent. ```sh npx -y @aigne/example-chat-bot --interactive ``` ### Using Different LLMs You can specify different models by setting the `MODEL` environment variable along with the corresponding API key. Below are configurations for several popular providers. | Provider | Environment Variables | |---|---| | OpenAI | `export MODEL=openai:gpt-4o` `export OPENAI_API_KEY=...` | | Anthropic | `export MODEL=anthropic:claude-3-opus-20240229` `export ANTHROPIC_API_KEY=...` | | Google Gemini | `export MODEL=gemini:gemini-1.5-flash` `export GEMINI_API_KEY=...` | | DeepSeek | `export MODEL=deepseek/deepseek-chat` `export DEEPSEEK_API_KEY=...` | | AWS Bedrock | `export MODEL=bedrock:anthropic.claude-3-sonnet-20240229-v1:0` `export AWS_ACCESS_KEY_ID=...` `export AWS_SECRET_ACCESS_KEY=...` `export AWS_REGION=...` | | Ollama | `export MODEL=llama3` `export OLLAMA_DEFAULT_BASE_URL="http://localhost:11434/v1"` | ## Example Library This section provides a curated list of examples, each demonstrating a specific capability or workflow pattern within the AIGNE Framework. Click on any card to navigate to the detailed guide for that example. ### Core Functionality ::::card-group ::link-card{title="Chatbot" description="Build a basic conversational agent that supports both one-shot and interactive modes." icon="bot" href="/en/docs/aigne-framework/examples-chat-bot-9dc03e/"} ::link-card{title="AFS Local FS" description="Create a chatbot that can read, write, and list files on the local file system." icon="folder" href="/en/docs/aigne-framework/examples-afs-local-fs-9dc03e/"} ::link-card{title="Memory" description="Implement an agent with persistent memory using the FSMemory plugin." icon="brain" href="/en/docs/aigne-framework/examples-memory-9dc03e/"} ::link-card{title="Nano Banana" description="Demonstrates how to create a chatbot with image generation capabilities." icon="image" href="/en/docs/aigne-framework/examples-nano-banana-9dc03e/"} :::: ### Workflow Patterns ::::card-group ::link-card{title="Sequential" description="Execute a series of agents in a specific, ordered sequence, like an assembly line." icon="arrow-right" href="/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/"} ::link-card{title="Concurrency" description="Run multiple agents simultaneously to perform tasks in parallel and improve efficiency." icon="git-branch" href="/en/docs/aigne-framework/examples-workflow-concurrency-9dc03e/"} ::link-card{title="Router" description="Create a manager agent that intelligently directs tasks to the appropriate specialized agent." icon="routes" href="/en/docs/aigne-framework/examples-workflow-router-9dc03e/"} ::link-card{title="Handoff" description="Enable seamless transitions where one agent passes its output to another for further processing." icon="refresh" href="/en/docs/aigne-framework/examples-workflow-handoff-9dc03e/"} ::link-card{title="Reflection" description="Build agents that can review and refine their own output for self-correction and improvement." icon="refresh" href="/en/docs/aigne-framework/examples-workflow-reflection-9dc03e/"} ::link-card{title="Orchestration" description="Coordinate multiple agents to solve complex problems that require collaboration." icon="users" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} ::link-card{title="Group Chat" description="Simulate a multi-agent discussion where agents can interact and build upon each other's messages." icon="message-square" href="/en/docs/aigne-framework/examples-workflow-group-chat-9dc03e/"} ::link-card{title="Code Execution" description="Safely execute dynamically generated code within an AI-driven workflow." icon="code-2" href="/en/docs/aigne-framework/examples-workflow-code-execution-9dc03e/"} :::: ### MCP and Integrations ::::card-group ::link-card{title="MCP Server" description="Run AIGNE agents as a Model Context Protocol (MCP) server to expose their skills." icon="server" href="/en/docs/aigne-framework/examples-mcp-server-9dc03e/"} ::link-card{title="MCP Blocklet" description="Integrate with a Blocklet and expose its functionalities as MCP skills." icon="box" href="/en/docs/aigne-framework/examples-mcp-blocklet-9dc03e/"} ::link-card{title="MCP GitHub" description="Interact with GitHub repositories using an agent connected to the GitHub MCP Server." icon="github" href="/en/docs/aigne-framework/examples-mcp-github-9dc03e/"} ::link-card{title="MCP Puppeteer" description="Leverage Puppeteer for automated web scraping and browser interaction." icon="navigation" href="/en/docs/aigne-framework/examples-mcp-puppeteer-9dc03e/"} ::link-card{title="MCP SQLite" description="Connect to an SQLite database to perform smart database operations." icon="database" href="/en/docs/aigne-framework/examples-mcp-sqlite-9dc03e/"} ::link-card{title="DID Spaces Memory" description="Persist agent memory using decentralized identity and storage with DID Spaces." icon="key" href="/en/docs/aigne-framework/examples-memory-did-spaces-9dc03e/"} :::: ## Debugging To gain insight into an agent's execution, you can enable debug logs or use the AIGNE observation server. ### View Debug Logs Set the `DEBUG` environment variable to `*` to output detailed logs, which include model calls and responses. ```sh DEBUG=* npx -y @aigne/example-chat-bot --interactive ``` ### Use the Observation Server The `aigne observe` command starts a local web server that provides a user-friendly interface to inspect execution traces, view detailed call information, and understand your agent’s behavior. This is a powerful tool for debugging and performance tuning. 1. Install the AIGNE CLI: ```sh npm install -g @aigne/cli ``` 2. Start the observation server: ```sh aigne observe ``` ![A terminal showing the aigne observe command starting the server.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) 3. View Traces: After running an agent, open your browser to `http://localhost:7893` to see a list of recent executions and inspect the details of each run. ![The AIGNE observability interface showing a list of traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) --- ## AFS Local FS URL: https://www.arcblock.io/en/docs/aigne-framework/examples-afs-local-fs-9dc03e/ This guide demonstrates how to build a chatbot capable of interacting with your local file system. By leveraging the AIGNE File System (AFS) and the `SystemFS` module, you can empower an AI agent to search, read, and manage files on your machine, turning it into a powerful local data expert. ## Overview The AIGNE File System (AFS) provides a virtual file system layer that gives AI agents a standardized way to access various storage systems. This example focuses on the `SystemFS` module, which bridges AFS to your local file system. When a user asks a question, the agent intelligently performs the following actions: ::::steps :::step{title="Search:"} It uses the `afs_search` tool to find relevant files within the designated directory based on the user's query. ::: :::step{title="Read:"} It identifies the most promising file from the search results and uses the `afs_read` tool to access its content. ::: :::step{title="Synthesize:"} It processes the file's content to formulate a comprehensive and accurate answer. ::: :::: This allows the agent to answer questions about your documents, code, or any other text-based files without manual guidance. ## Prerequisites Before you begin, ensure you have the following installed and configured: - [Node.js](https://nodejs.org) (version 20.0 or higher) - An [OpenAI API key](https://platform.openai.com/api-keys) ## Quick Start You can run this example directly without a local installation using `npx`. 1. Set your OpenAI API Key: ```bash export OPENAI_API_KEY=YOUR_OPENAI_API_KEY ``` 2. Run the Chatbot: You can mount any local directory. For this example, we'll clone the AIGNE framework and use its documentation as the knowledge base. ```bash # Clone the repository to use its docs git clone https://github.com/AIGNE-io/aigne-framework # Start the chatbot in interactive mode, pointing to the docs npx -y @aigne/example-afs-local-fs --path ./aigne-framework --interactive ``` Alternatively, you can ask a single, specific question: ```bash npx -y @aigne/example-afs-local-fs --path ./aigne-framework --input "What is AIGNE?" ``` ### Example Interaction Here is an example of the agent's process when asked, "What is AIGNE?": ``` 👤 You: "What is AIGNE?" 🤖 Agent thinks: I need to find information about AIGNE in the provided files. I will start by searching. → Calls: afs_search(query: "AIGNE") 📁 Found 15 matching files: • docs/getting-started/what-is-aigne.md ⭐ (most relevant) • README.md • docs/core-concepts/overview.md ... 🤖 Agent thinks: The first result seems most relevant. I will read it to answer the user's question. → Calls: afs_read("docs/getting-started/what-is-aigne.md") 📄 File loaded (2.4 KB) 🤖 AI: "AIGNE is a framework and runtime engine for building LLM-powered applications and AI agents. It provides: • A unified Agentic File System (AFS) interface • Support for multiple LLM providers (OpenAI, Anthropic, etc.) • Tools for building autonomous agents • Integration with external services via MCP Would you like me to walk you through a quick-start tutorial, or would you prefer to see specific examples?" ``` The agent successfully found the correct file, read its contents, and provided a summarized, helpful response. ## Connecting to an AI Model The agent requires a connection to a Large Language Model (LLM) to function. If you run the example without providing an API key, you will be prompted to choose a connection method. ![Initial setup prompt when no API key is found.](https://media.arcblock.io/lib/40/40d2d17af24c49bf.w1600.webp) You have three options: 1. Connect to AIGNE Hub (Recommended): This is the easiest way to get started. Your browser will open an authorization page. New users receive free credits to use the service. ![Authorize AIGNE CLI to connect to AIGNE Hub.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) 2. Connect to a Self-Hosted AIGNE Hub: If you are running your own instance of AIGNE Hub, select this option and enter its URL. ![Enter the URL for a self-hosted AIGNE Hub.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) 3. Use a Third-Party Model Provider: You can directly connect to a provider like OpenAI by setting the corresponding environment variable. ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` For a list of supported providers and their required environment variables, refer to the example `.env.local.example` file in the source code. ## How It Works The implementation can be broken down into three main steps, as illustrated in the diagram below: ![AFS Local FS](https://media.arcblock.io/lib/d6/d61731d25eb2b246.w1600.webp) ### 1. Create a LocalFS Module First, instantiate the `LocalFS` module, specifying the local path to the directory you want the agent to access and an optional description. **create-local-fs.ts** ```typescript import { LocalFS } from "@aigne/afs-local-fs"; const localFS = new LocalFS({ localPath: './aigne-framework', description: 'AIGNE framework documentation' }); ``` ### 2. Mount the Module in AFS Next, create an `AFS` instance and `mount` the `localFS` module. This makes the local directory available to any agent that has access to this AFS instance. **mount-module.ts** ```typescript import { AFS } from "@aigne/afs"; import { AFSHistory } from "@aigne/afs-history"; const afs = new AFS() .mount(new AFSHistory({ storage: { url: ":memory:" } })) .mount(localFS); // Mounted at the default path /modules/local-fs ``` ### 3. Create and Configure the AI Agent Finally, create an `AIAgent` and provide it with the `afs` instance. The agent automatically gains access to AFS tools for file system interaction. **create-agent.ts** ```typescript import { AIAgent } from "@aigne/core"; const agent = AIAgent.from({ instructions: "Help users find and read files from the local file system.", inputKey: "message", afs, // The agent inherits afs_list, afs_read, afs_write, and afs_search }); ``` ### Available AFS Tools By connecting the agent to AFS, it can use the following sandboxed tools to operate on the mounted directory: - `afs_list`: Lists files and subdirectories. - `afs_read`: Reads the content and metadata of a specific file. - `afs_write`: Creates a new file or overwrites an existing one. - `afs_search`: Performs a full-text search across all files in the directory. ## Installation and Local Execution If you prefer to run the example from the source code, follow these steps. 1. Clone the Repository: ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` 2. Install Dependencies: Navigate to the example directory and install the necessary packages using `pnpm`. ```bash cd aigne-framework/examples/afs-local-fs pnpm install ``` 3. Run the Example: Use the `pnpm start` command to run the chatbot. ```bash # Mount the current directory pnpm start --path . # Mount a specific directory with a custom description pnpm start --path ~/Documents --description "My Documents" # Run in interactive chat mode pnpm start --path . --interactive ``` ## Use Cases This example provides a foundation for several practical applications. ### Documentation Chat Mount your project's documentation folder to create a chatbot that can answer user questions about your project. ```typescript const afs = new AFS() .mount(new LocalFS({ localPath: './docs', description: 'Project documentation' })); ``` ### Codebase Analysis Allow an AI agent to access your source code to help with analysis, refactoring, or explaining complex logic. ```typescript const afs = new AFS() .mount(new LocalFS({ localPath: './src', description: 'Source code' })); ``` ### File Organization Build an agent that can help you sort and manage files in a directory, such as your "Downloads" folder. ```typescript const afs = new AFS() .mount(new LocalFS({ localPath: '~/Downloads', description: 'Downloads folder' })); ``` ### Multi-Directory Access Mount several directories to give the agent a broader context, allowing it to search across your source code, documentation, and tests simultaneously. ```typescript const afs = new AFS() .mount("/docs", new LocalFS({ localPath: './docs' })) .mount("/src", new LocalFS({ localPath: './src' })) .mount("/tests", new LocalFS({ localPath: './tests' })); ``` ## Summary You have learned how to use the AIGNE Framework to create a chatbot that can interact with a local file system. This powerful capability enables a wide range of applications, from intelligent documentation search to automated code analysis. For further reading, explore the following related examples and packages: ::::card-group ::link-card{title="Memory Example" description="Learn how to add conversational memory to your chatbot." icon="brain" href="/en/docs/aigne-framework/examples-memory-9dc03e/"} ::link-card{title="MCP Server Example" description="Discover how to integrate your agent with external services using MCP." icon="server" href="/en/docs/aigne-framework/examples-mcp-server-9dc03e/"} :::: --- ## Chatbot URL: https://www.arcblock.io/en/docs/aigne-framework/examples-chat-bot-9dc03e/ This guide provides a comprehensive walkthrough of the agent-based chatbot example. You will learn how to run the chatbot in different modes, connect it to various AI model providers, and use the AIGNE observability tools to debug its execution. This example is designed to work out-of-the-box, allowing you to get started without any local installation. ## Overview This example demonstrates how to create and run a simple yet powerful agent-based chatbot using the AIGNE Framework. It supports two primary modes of operation: - One-shot mode: The chatbot takes a single input, provides a response, and then exits. - Interactive mode: The chatbot engages in a continuous conversation until you decide to end the session. The chatbot can be configured to use different AI models and can accept input directly from the command line or through a pipeline. ## Prerequisites Before running the example, ensure you have the following installed on your system: - [Node.js](https://nodejs.org) (version 20.0 or higher) - An [OpenAI API key](https://platform.openai.com/api-keys) or access to an AIGNE Hub for model interaction. ## Quick Start You can run this example directly using `npx` without cloning the repository or installing any dependencies locally. ### Running the Example Execute the following commands in your terminal to run the chatbot. Run in default one-shot mode: **npx command** ```bash npx -y @aigne/example-chat-bot ``` Run in interactive chat mode using the `--interactive` flag: **npx command** ```bash npx -y @aigne/example-chat-bot --interactive ``` Use pipeline input to provide a prompt directly: **npx command** ```bash echo "Tell me about AIGNE Framework" | npx -y @aigne/example-chat-bot ``` ### Connecting to an AI Model The first time you run the example, it will prompt you to connect to an AI model service since no API keys are configured. The following diagram illustrates the connection options available: ```d2 direction: down Chatbot-Example: { label: "Chatbot Example\n(@aigne/example-chat-bot)" shape: rectangle } Connection-Options: { label: "Connection Options" shape: rectangle style: { stroke-dash: 4 } Official-AIGNE-Hub: { label: "1. Official AIGNE Hub\n(Recommended)" icon: "https://www.arcblock.io/image-bin/uploads/89a24f04c34eca94f26c9dd30aec44fc.png" } Self-Hosted-Hub: { label: "2. Self-Hosted AIGNE Hub" icon: "https://www.arcblock.io/image-bin/uploads/89a24f04c34eca94f26c9dd30aec44fc.png" } Third-Party-Provider: { label: "3. Third-Party Provider\n(e.g., OpenAI)" shape: rectangle } } Blocklet-Store: { label: "Blocklet Store" icon: "https://store.blocklet.dev/assets/z8ia29UsENBg6tLZUKi2HABj38Cw1LmHZocbQ/logo.png" } Chatbot-Example -> Connection-Options: "Prompts user to connect to AI model" Connection-Options.Self-Hosted-Hub -> Blocklet-Store: "Install from" ``` ![Initial setup prompt for connecting an AI model.](https://media.arcblock.io/lib/b5/b547e1eb5cde9c69.w1600.webp) You have several options to proceed: #### 1. Connect to the Official AIGNE Hub (Recommended) This is the easiest way to get started. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your web browser will open a page to authorize the AIGNE CLI. 3. Follow the on-screen instructions to approve the connection. New users receive a complimentary token grant to use the service. ![Authorize AIGNE CLI to connect to AIGNE Hub.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### 2. Connect to a Self-Hosted AIGNE Hub If you are running your own instance of AIGNE Hub: 1. Select the second option: `Connect to a self-hosted AIGNE Hub instance`. 2. Enter the URL of your self-hosted AIGNE Hub when prompted. 3. Follow the subsequent prompts to complete the connection. If you need to set up a self-hosted AIGNE Hub, you can install it from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ). ![Enter the URL for a self-hosted AIGNE Hub.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### 3. Connect via a Third-Party Model Provider You can also connect directly to a third-party AI model provider, such as OpenAI, by setting the appropriate environment variables. For example, to use OpenAI, set your API key as follows: **Set OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After setting the environment variable, run the example again. For a list of supported providers and their required environment variables, refer to the example configuration file. ## Local Installation and Usage For development purposes, you may want to clone the repository and run the example locally. ### 1. Install AIGNE CLI First, install the AIGNE Command Line Interface (CLI) globally. **Install AIGNE CLI** ```bash npm install -g @aigne/cli ``` ### 2. Clone the Repository Clone the `aigne-framework` repository and navigate to the `chat-bot` example directory. **Clone repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework cd aigne-framework/examples/chat-bot ``` ### 3. Run the Example Locally Use the `pnpm start` command to run the chatbot. Run in default one-shot mode: **pnpm command** ```bash pnpm start ``` Run in interactive chat mode: **pnpm command** ```bash pnpm start --interactive ``` Use pipeline input: **pnpm command** ```bash echo "Tell me about AIGNE Framework" | pnpm start ``` ## Command-Line Options The chatbot script accepts several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. If omitted, runs in one-shot mode. | `Disabled` | | `--model ` | Specifies the AI model to use. The format is `provider[:model]`. Examples: `openai` or `openai:gpt-4o-mini`. | `openai` | | `--temperature ` | Sets the temperature for model generation, controlling randomness. | Provider default | | `--top-p ` | Sets the top-p (nucleus sampling) value for model generation. | Provider default | | `--presence-penalty ` | Sets the presence penalty value to influence topic diversity. | Provider default | | `--frequency-penalty ` | Sets the frequency penalty value to reduce repetitive output. | Provider default | | `--log-level ` | Sets the logging level. Options are `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. | `INFO` | | `--input`, `-i ` | Provides the input prompt directly as an argument. | `None` | ## Debugging with AIGNE Observe AIGNE includes a powerful local observability tool for debugging and analyzing agent execution. The `aigne observe` command starts a local web server that provides a user interface to inspect execution traces. First, start the observation server in your terminal: **aigne observe** ```bash aigne observe ``` ![Terminal output showing the aigne observe server running.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) After running the chatbot, you can open the provided URL (typically `http://localhost:7893`) in your browser to view a list of recent agent executions. This interface allows you to inspect detailed information for each run, including inputs, outputs, model calls, and performance metrics, which is invaluable for debugging and optimization. ![AIGNE observability interface showing a list of traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This example provides a practical foundation for building agent-based chatbots with the AIGNE Framework. You have learned how to run the example, connect it to various AI models, and utilize the built-in observability tools for debugging. For more advanced topics and examples, you may find the following documents helpful: ::::card-group ::link-card{title="Memory" description="Learn how to add memory to your chatbot to maintain context across conversations." icon="brain" href="/en/docs/aigne-framework/examples-memory-9dc03e/"} ::link-card{title="AIGNE Core Concepts" description="Dive deeper into the fundamental building blocks of the AIGNE Framework." icon="book-open" href="/en/docs/aigne-framework/developer-guide-core-concepts-9dc03e/"} :::: --- ## MCP Blocklet URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-blocklet-9dc03e/ This document provides instructions on how to utilize the AIGNE Framework and the Model Context Protocol (MCP) to interact with applications hosted on the Blocklet platform. This example supports one-shot execution, interactive chat mode, and customizable settings for models and I/O pipelines. ## Prerequisites Before proceeding, ensure the following components are installed and configured on your system: - Node.js: Version 20.0 or higher. - npm: Included with Node.js installation. - OpenAI API Key: Required for interacting with OpenAI models. You can obtain one from the [OpenAI API keys page](https://platform.openai.com/api-keys). The following dependencies are optional and are only required if you intend to run the example from the source code: - Bun: A JavaScript runtime, used here for running tests and examples. - pnpm: A package manager. ## Quick Start This section provides instructions for running the example directly without a local installation. ### Run the Example First, set the URL of your target Blocklet application as an environment variable. **Set your Blocklet app URL** ```bash export BLOCKLET_APP_URL="https://xxx.xxxx.xxx" ``` You can execute the example in several modes: - One-Shot Mode (Default): Sends a single request and receives a response. ```bash npx -y @aigne/example-mcp-blocklet ``` - Interactive Chat Mode: Starts a continuous chat session. ```bash npx -y @aigne/example-mcp-blocklet --interactive ``` - Pipeline Input: Uses piped input as the prompt. ```bash echo "What are the features of this blocklet app?" | npx -y @aigne/example-mcp-blocklet ``` ### Connect to an AI Model Executing the example requires a connection to an AI model. On the first run, if no connection is configured, you will be prompted to choose a connection method. ![Initial connection prompt for AI model setup](https://media.arcblock.io/lib/b5/b547e1eb5cde9c69.w1600.webp) There are several methods to establish a connection: #### 1. Connect via the Official AIGNE Hub This is the recommended approach. Selecting this option will open your web browser to the official AIGNE Hub authentication page. Follow the on-screen instructions to complete the connection. New users are automatically granted 400,000 tokens for use. ![Authorize AIGNE CLI to connect to AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### 2. Connect via a Self-Hosted AIGNE Hub If you operate your own instance of AIGNE Hub, select the second option. You will be prompted to enter the URL of your self-hosted Hub to complete the connection. ![Enter the URL of your self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) To deploy a self-hosted AIGNE Hub, you can install it from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ?utm_source=www.arcblock.io&utm_medium=blog_link&utm_campaign=default&utm_content=store.blocklet.dev#:~:text=%F0%9F%9A%80%20Get%20Started%20in%20Minutes). #### 3. Connect via a Third-Party Model Provider You can connect directly to a third-party model provider, such as OpenAI, by setting the appropriate API key as an environment variable. **Set OpenAI API Key** ```bash export OPENAI_API_KEY="your_openai_api_key_here" ``` For a comprehensive list of supported environment variables for various providers (e.g., DeepSeek, Google Gemini), refer to the `.env.local.example` file within the example's source code. After configuring the environment variables, run the example command again. ### Debugging The AIGNE Framework includes a local observability server for monitoring and analyzing agent execution data. This tool is essential for debugging, performance tuning, and understanding agent behavior. To start the server, run the following command: **Start the observation server** ```bash aigne observe ``` ![Terminal output showing the aigne observe command running](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) Once the server is running, you can access the web interface at `http://localhost:7893` to view a list of recent agent traces and inspect detailed call information. ![Aigne Observability web interface showing a list of traces](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Installation from Source For development purposes, you can run the example from a local clone of the repository. ### 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the required packages using `pnpm`. ```bash cd aigne-framework/examples/mcp-blocklet pnpm install ``` ### 3. Run the Example Execute the start script to run the application. **Run in one-shot mode** ```bash pnpm start ``` You can also provide the Blocklet application URL directly as an argument. ```bash pnpm start https://your-blocklet-app-url ``` ## Run Options The application supports several command-line parameters for customization. | Parameter | Description | Default | |---|---|---| | `--interactive` | Enables interactive chat mode. | Disabled | | `--model ` | Specifies the AI model to use. Format is `provider[:model]`. Examples: `openai` or `openai:gpt-4o-mini`. | `openai` | | `--temperature ` | Sets the temperature for model generation. | Provider default | | `--top-p ` | Sets the top-p sampling value. | Provider default | | `--presence-penalty ` | Sets the presence penalty value. | Provider default | | `--frequency-penalty ` | Sets the frequency penalty value. | Provider default | | `--log-level ` | Sets the logging level. Options: `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`. | `INFO` | | `--input`, `-i ` | Provides input directly via the command line. | None | When running from source using `pnpm`, you must use `--` to pass arguments to the script. Examples: **Run in interactive chat mode** ```bash pnpm start -- --interactive ``` **Set the logging level to DEBUG** ```bash pnpm start -- --log-level DEBUG ``` **Use pipeline input** ```bash echo "What are the features of this blocklet app?" | pnpm start ``` ## Summary This guide has detailed the process for running the MCP Blocklet example, including quick-start execution, model configuration, debugging, and local installation. For more advanced use cases and related concepts, refer to the following documentation. ::::card-group ::link-card{title="MCP Server" description="Learn how to run AIGNE Framework agents as a Model Context Protocol (MCP) Server." icon="server" href="/en/docs/aigne-framework/examples-mcp-server-9dc03e/"} ::link-card{title="MCP Agent" description="Understand how to connect to and interact with external systems via MCP." icon="bot" href="/en/docs/aigne-framework/developer-guide-agents-mcp-agent-9dc03e/"} :::: --- ## MCP DID Spaces URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-did-spaces-9dc03e/ This document provides a comprehensive guide to building a chatbot integrated with DID Spaces via the Model Context Protocol (MCP). Following these instructions will enable you to create an AI agent that can securely access and manage files in a decentralized storage environment, leveraging the capabilities of the [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework). ## Prerequisites To ensure successful execution of this example, verify that the following components are installed and configured: - Node.js: Version 20.0 or a more recent version. - OpenAI API Key: An active API key is required for the AI model. Keys can be obtained from the [OpenAI Platform](https://platform.openai.com/api-keys). - DID Spaces MCP Server Credentials: Authentication details are necessary for interaction with your designated DID Space. ## Quick Start This example can be executed directly from your terminal without a local installation by using `npx`. ### 1. Set Environment Variables Begin by configuring the environment variables with your DID Spaces server credentials. The URL for your space and an access key can be generated from your Blocklet's administration settings. **Set DID Spaces Credentials** ```bash # Replace with your DID Spaces application URL export DID_SPACES_URL="https://spaces.staging.arcblock.io/app" # Create a key in Profile -> Settings -> Access Keys, setting Auth Type to "Simple" export DID_SPACES_AUTHORIZATION="blocklet-xxx" ``` ### 2. Run the Example With the environment variables set, execute the command below to initialize the chatbot. **Run the Example** ```bash npx -y @aigne/example-mcp-did-spaces ``` ### 3. Connect to an AI Model The chatbot requires a connection to a Large Language Model (LLM) to operate. On the first run, a prompt will appear to guide you through the connection setup. ![Initial prompt for AI model connection](https://media.arcblock.io/lib/b5/b547e1eb5cde9c69.w1600.webp) There are three primary methods for establishing a connection: #### Option 1: AIGNE Hub (Recommended) This is the most direct method. The official AIGNE Hub provides new users with complimentary tokens. To use this option, select the first choice in the prompt. Your web browser will open to the AIGNE Hub authorization page, where you can approve the connection request. ![Authorize AIGNE Hub connection](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### Option 2: Self-Hosted AIGNE Hub For users operating a private AIGNE Hub instance, select the second option. You will be prompted to enter the URL of your self-hosted hub. Instructions for deploying a personal AIGNE Hub are available at the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ). ![Connect to a self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### Option 3: Third-Party Model Provider Direct integration with third-party LLM providers such as OpenAI is also supported. Configure the respective API key as an environment variable and execute the run command again. **Configure OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` For additional configuration examples, including providers like DeepSeek and Google Gemini, consult the `.env.local.example` file within the source repository. Once the AI model is connected, the example will perform a series of test operations against your DID Space, log the outcomes to the console, and generate a markdown file summarizing the results. ## How It Works This example employs an `MCPAgent` to interface with a DID Spaces server using the Model Context Protocol (MCP). This protocol enables the agent to dynamically discover and utilize "skills," which are direct mappings to DID Spaces functionalities. The following diagram illustrates the operational flow: ```d2 direction: down AI-Agent: { label: "AI Agent" shape: rectangle } MCPAgent: { label: "MCPAgent" shape: rectangle } DID-Spaces-Server: { label: "DID Spaces MCP Server" shape: rectangle Skills: { label: "Available Skills" shape: rectangle list-objects: "list_objects" write-object: "write_object" read-object: "read_object" head-space: "head_space" delete-object: "delete_object" } } DID-Space: { label: "DID Space" shape: cylinder } AI-Agent -> MCPAgent: "3. Execute command\n(e.g., 'list files')" MCPAgent -> DID-Spaces-Server: "1. Connect & Authenticate" DID-Spaces-Server -> MCPAgent: "2. Provide Skills" MCPAgent -> DID-Space: "4. Perform operation via skill" ``` The operational flow is as follows: 1. The `MCPAgent` connects to the designated DID Spaces MCP server endpoint. 2. It authenticates using the provided authorization credentials. 3. The server makes a set of skills, such as `list_objects` and `write_object`, available to the agent. 4. The `MCPAgent` integrates these skills, allowing the primary AI agent to perform file and data management tasks within the DID Space in response to user input or programmed logic. ### Available Skills The integration exposes several key DID Spaces operations as skills that the agent can utilize: | Skill | Description | |---|---| | `head_space` | Retrieves metadata about the DID Space. | | `read_object` | Reads the content of a specified object (file). | | `write_object` | Writes new content to an object (file). | | `list_objects` | Lists all objects (files) within a directory. | | `delete_object` | Deletes a specified object (file). | ## Configuration For production deployments, the agent configuration should be updated to target your specific MCP server and employ secure authentication tokens. The `MCPAgent` is instantiated with the server URL and appropriate authorization headers. **agent-config.ts** ```typescript const mcpAgent = await MCPAgent.from({ url: "YOUR_MCP_SERVER_URL", transport: "streamableHttp", opts: { requestInit: { headers: { Authorization: "Bearer YOUR_TOKEN", }, }, }, }); ``` ## Debugging The `aigne observe` command provides a tool for monitoring and analyzing the agent's runtime behavior. It launches a local web server that visualizes execution traces, offering insights into inputs, outputs, tool interactions, and performance metrics. 1. Start the observation server: **aigne observe** ```bash aigne observe ``` ![AIGNE Observe server starting in the terminal](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) 2. View execution traces: Access the web interface at `http://localhost:7893` to review a list of recent agent executions. Each trace can be inspected for a detailed analysis of the agent's operations. ![AIGNE Observe trace list](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Local Installation and Testing For developers intending to modify the source code, the following steps outline the process for local setup and testing. ### 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Change to the example's directory and use `pnpm` to install the required packages. ```bash cd aigne-framework/examples/mcp-did-spaces pnpm install ``` ### 3. Run the Example Execute the start script to run the application from the local source. ```bash pnpm start ``` ### 4. Run Tests To validate the integration and functionality, execute the test suite. ```bash pnpm test:llm ``` The test process will establish a connection to the MCP server, enumerate the available skills, and perform basic DID Spaces operations to confirm the integration is functioning as expected. --- ## MCP GitHub URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-github-9dc03e/ This document provides a comprehensive guide to an example that demonstrates how to interact with GitHub repositories using the AIGNE Framework and the GitHub MCP (Model Context Protocol) Server. You will learn how to set up and run the example, enabling an AI agent to perform various GitHub operations like searching repositories and managing files. ## Overview The example showcases the integration of an `MCPAgent` that connects to a GitHub MCP server. This agent equips the AI with a suite of tools (skills) to interact with the GitHub API. The workflow allows a user to make requests in natural language, which the AI agent then translates into specific function calls to the GitHub agent to perform actions such as searching for repositories, reading file contents, or creating issues. ```d2 direction: down User: { shape: c4-person } AIGNE-Framework: { label: "AIGNE Framework" shape: rectangle AIAgent: { label: "AI Agent\n(@aigne/core)" shape: rectangle } MCPAgent: { label: "GitHub MCP Agent\n(Skill)" shape: rectangle } AIAgent -> MCPAgent: "Uses skill" } GitHub-MCP-Server: { label: "GitHub MCP Server\n(@modelcontextprotocol/server-github)" shape: rectangle } GitHub-API: { label: "GitHub API" shape: cylinder } AI-Model-Provider: { label: "AI Model Provider\n(e.g., OpenAI, AIGNE Hub)" shape: cylinder } AIGNE-Observe: { label: "AIGNE Observe\n(Debugging UI)" shape: rectangle } User -> AIGNE-Framework.AIAgent: "1. Natural language request" AIGNE-Framework.AIAgent -> AI-Model-Provider: "2. Process request" AI-Model-Provider -> AIGNE-Framework.AIAgent: "3. Return function call" AIGNE-Framework.AIAgent -> AIGNE-Framework.MCPAgent: "4. Execute function call" AIGNE-Framework.MCPAgent -> GitHub-MCP-Server: "5. Send command" GitHub-MCP-Server -> GitHub-API: "6. Call GitHub API" GitHub-API -> GitHub-MCP-Server: "7. Return API response" GitHub-MCP-Server -> AIGNE-Framework.MCPAgent: "8. Return result" AIGNE-Framework.MCPAgent -> AIGNE-Framework.AIAgent: "9. Return result" AIGNE-Framework.AIAgent -> AI-Model-Provider: "10. Process result" AI-Model-Provider -> AIGNE-Framework.AIAgent: "11. Return natural language response" AIGNE-Framework.AIAgent -> User: "12. Final response" AIGNE-Framework -> AIGNE-Observe: "Sends execution traces" ``` ## Prerequisites Before proceeding, ensure your system meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Included with Node.js. - GitHub Personal Access Token: A token with the necessary permissions for the repositories you intend to interact with. You can create one from your [GitHub settings](https://github.com/settings/tokens). - AI Model Provider Account: An API key from a provider like [OpenAI](https://platform.openai.com/api-keys) or a connection to an AIGNE Hub instance. ## Quick Start You can run this example directly without a local installation using `npx`. First, set your GitHub token as an environment variable. **Set your GitHub token** ```bash export GITHUB_TOKEN=YOUR_GITHUB_TOKEN ``` Next, execute the example. **Run the example** ```bash npx -y @aigne/example-mcp-github ``` ### Connect to an AI Model Upon first execution, if no AI model is configured, you will be prompted to connect one. You have several options to proceed: #### 1. Connect to the Official AIGNE Hub This is the recommended approach. Selecting this option will open your browser to the official AIGNE Hub page. Follow the on-screen instructions to authorize the connection. New users receive complimentary credits to get started. #### 2. Connect to a Self-Hosted AIGNE Hub If you operate your own instance of AIGNE Hub, choose this option. You will be prompted to enter the URL of your self-hosted Hub to complete the connection. #### 3. Configure a Third-Party Model Provider You can also connect directly to a supported third-party model provider, such as OpenAI. To do this, set the provider's API key as an environment variable. For example, to use OpenAI, configure your `OPENAI_API_KEY`: **Set your OpenAI API key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After setting the environment variable, run the `npx` command again. For a list of supported environment variables for other providers, refer to the `.env.local.example` file in the project source. ## Installation from Source For developers who wish to inspect or modify the code, follow these steps to run the example from a local clone. ### 1. Clone the Repository Clone the main AIGNE Framework repository from GitHub. ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and install the necessary dependencies using `pnpm`. ```bash cd aigne-framework/examples/mcp-github pnpm install ``` ### 3. Run the Example Execute the start script to run the example. **Run in one-shot mode** ```bash pnpm start ``` The example also supports interactive chat mode and can accept input piped from other commands. **Run in interactive chat mode** ```bash pnpm start -- --interactive ``` **Use pipeline input** ```bash echo "Search for repositories related to 'modelcontextprotocol'" | pnpm start ``` ### Command-Line Options You can customize the execution with the following command-line parameters: | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | Specify the AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input, -i ` | Specify input directly as an argument. | None | ## Code Example The following TypeScript code demonstrates the core logic of the example. It initializes an AI model, sets up the `MCPAgent` for GitHub, and invokes an `AIAgent` to perform a repository search. **index.ts** ```typescript import { AIAgent, AIGNE, MCPAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; // Load environment variables const { OPENAI_API_KEY, GITHUB_TOKEN } = process.env; // Initialize OpenAI model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // Initialize GitHub MCP agent const githubMCPAgent = await MCPAgent.from({ command: "npx", args: ["-y", "@modelcontextprotocol/server-github"], env: { GITHUB_TOKEN, }, }); // Create AIGNE instance with the model and GitHub skills const aigne = new AIGNE({ model, skills: [githubMCPAgent], }); // Create an AI agent with instructions for interacting with GitHub const agent = AIAgent.from({ instructions: `\ ## GitHub Interaction Assistant You are an assistant that helps users interact with GitHub repositories. You can perform various GitHub operations like: 1. Searching repositories 2. Getting file contents 3. Creating or updating files 4. Creating issues and pull requests 5. And many more GitHub operations Always provide clear, concise responses with relevant information from GitHub. `, }); // Invoke the agent to search for repositories const result = await aigne.invoke( agent, "Search for repositories related to 'modelcontextprotocol'", ); console.log(result); // Expected Output: // I found several repositories related to 'modelcontextprotocol': // // 1. **modelcontextprotocol/servers** - MCP servers for various APIs and services // 2. **modelcontextprotocol/modelcontextprotocol** - The main ModelContextProtocol repository // ... // Shutdown the AIGNE instance when done await aigne.shutdown(); ``` ## Available Operations The GitHub MCP server exposes a wide range of GitHub functionalities as skills that the AI agent can use, including: - Repository Operations: Search, create, and get information about repositories. - File Operations: Get file contents, create or update files, and push multiple files in a single commit. - Issue and PR Operations: Create issues and pull requests, add comments, and merge pull requests. - Search Operations: Search code, issues, and users. - Commit Operations: List commits and get commit details. ## Debugging with AIGNE Observe To inspect and analyze the behavior of your agent, you can use the `aigne observe` command. This tool starts a local web server that provides a user interface for viewing execution traces, call details, and other runtime data. To start the observation server, run: **Start the AIGNE observe server** ```bash aigne observe ``` Once the server is running, you can access the web interface in your browser to view a list of recent executions and drill down into the details of each trace. This tool is invaluable for debugging, understanding how the agent interacts with tools and models, and optimizing performance. --- ## MCP Puppeteer URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-puppeteer-9dc03e/ This guide provides a step-by-step demonstration of how to use the AIGNE Framework with a Puppeteer MCP Server for automated web scraping. By following this example, you will learn to build and run an AI agent capable of navigating to a website and extracting its content. ## Overview This example showcases an integration between an `AIAgent` and a `MCPAgent` that controls a Puppeteer instance. The `AIAgent` receives a natural language command to extract content from a URL. It then delegates the web automation tasks to the Puppeteer agent, which navigates to the specified page and executes JavaScript to scrape the content. The general workflow is as follows: ```mermaid flowchart LR in(In) out(Out) agent(AI Agent) puppeteer(Puppeteer MCP Agent) navigate(Navigate to URL) evaluate(Evaluate JS) in --> agent <--> puppeteer subgraph MCP Agent puppeteer <--> navigate puppeteer <--> evaluate end agent --> out classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px,color:#b35b39,font-weight:bolder; classDef processing fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px,color:#6B8F3C,font-weight:bolder; class in inputOutput class out inputOutput class agent processing class puppeteer processing class navigate processing class evaluate processing ``` The sequence of operations for summarizing website content is illustrated below: ```d2 shape: sequence_diagram User: { shape: c4-person } AI: { label: "AI Agent" } P: { label: "Puppeteer MCP Agent" } N: { label: "Navigate to URL" } E: { label: "Evaluate JS" } User -> AI: "summarize content from https://www.arcblock.io" AI -> P: "extract content from https://www.arcblock.io" P -> N: "navigate to https://www.arcblock.io" N -> P: "navigation completed" P -> E: "evaluate document.body.innerText" E -> P: "content extracted" E -> AI: "extracted content as context" AI -> User: "The content is as follows: ..." ``` ## Prerequisites Before running the example, ensure the following requirements are met: - Node.js version 20.0 or higher. - An active OpenAI API key. ## Quick Start You can run this example directly without cloning the repository using `npx`. ### Run the Example Execute the following commands in your terminal. The example supports a one-shot mode, an interactive chat mode, and can receive input via a pipeline. **Run in one-shot mode** ```sh # Run in one-shot mode (default) npx -y @aigne/example-mcp-puppeteer ``` **Run in interactive chat mode** ```sh # Run in interactive chat mode npx -y @aigne/example-mcp-puppeteer --interactive ``` **Use pipeline input** ```sh # Use pipeline input echo "extract content from https://www.arcblock.io" | npx -y @aigne/example-mcp-puppeteer ``` ### Connect to an AI Model On the first run, if no model provider is configured, the application will prompt you to connect to one. ![Initial connection prompt for AI model](https://media.arcblock.io/lib/fd/fd3700482377c3ca.w1600.webp) You have several options to proceed: - Connect via the official AIGNE Hub: This is the recommended option. Choosing it will open your web browser to the AIGNE Hub, where you can authorize the connection. New users receive a complimentary token balance for trial purposes. ![Authorize connection to AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) - Connect via a self-hosted AIGNE Hub: If you host your own AIGNE Hub, select this option and enter the URL of your instance to complete the connection. You can deploy your own AIGNE Hub from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ?utm_source=www.arcblock.io&utm_medium=blog_link&utm_campaign=default&utm_content=store.blocklet.dev#:~:text=%F0%9F%9A%80%20Get%20Started%20in%20Minutes). ![Connect to a self-hosted AIGNE Hub instance](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) - Connect via a third-party model provider: You can configure an API key from a provider like OpenAI directly using environment variables. **Configure OpenAI API Key** ```sh export OPENAI_API_KEY="YOUR_API_KEY" ``` For a comprehensive list of supported providers and variables, refer to the example `.env.local.example` file within the project. After setting the environment variable, run the command again. ## Installation from Source To examine the code or make modifications, you can clone the repository and run the example locally. ### 1. Clone the Repository **Clone the aigne-framework repository** ```sh git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the required packages using `pnpm`. **Install dependencies** ```sh cd aigne-framework/examples/mcp-puppeteer pnpm install ``` ### 3. Run the Example Execute the start script to run the application. **Run the example from source** ```sh pnpm start ``` To pass command-line arguments to the script, separate them with `--`. **Run in chat mode from source** ```sh pnpm start -- --interactive ``` ## Code Example The following TypeScript code demonstrates the core logic for setting up the AIGNE instance, configuring the Puppeteer MCP agent, and invoking the AI agent to extract web content. **agent.ts** ```typescript import { AIAgent, AIGNE, MCPAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // Initialize the OpenAI model with an API key const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // Create an MCPAgent that runs the Puppeteer server const puppeteerMCPAgent = await MCPAgent.from({ command: "npx", args: ["-y", "@modelcontextprotocol/server-puppeteer"], }); // Initialize the AIGNE instance with the model and the Puppeteer agent as a skill const aigne = new AIGNE({ model, skills: [puppeteerMCPAgent], }); // Define the AI agent with instructions for web content extraction const agent = AIAgent.from({ instructions: `\ ## Steps to extract content from a website 1. navigate to the url 2. evaluate document.body.innerText to get the content `, }); // Invoke the agent with a prompt const result = await aigne.invoke( agent, "extract content from https://www.arcblock.io", ); console.log(result); // Expected output: // { // $message: "The content extracted from the website [ArcBlock](https://www.arcblock.io) is as follows:\n\n---\n\n**Redefining Software Architect and Ecosystems**\n\nA total solution for building decentralized applications ...", // } // Shut down the AIGNE instance and its agents await aigne.shutdown(); ``` ## Command-Line Options The application supports several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | Specify the AI model. Examples: `openai`, `openai:gpt-4o-mini`. | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input`, `-i ` | Provide input directly as an argument. | None | ## Debugging The AIGNE Framework includes an observability tool to help you monitor and debug agent executions. To start the observation server, run: **Start the observability server** ```sh aigne observe ``` ![AIGNE observability server running in the terminal](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) Once running, you can open the web interface in your browser to view a detailed list of execution traces, inspect inputs, outputs, and tool calls for each agent. ![AIGNE observability interface showing a list of traces](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) This tool is essential for understanding agent behavior, diagnosing issues, and optimizing performance. --- ## MCP Server URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-server-9dc03e/ This guide provides instructions on how to run AIGNE Framework agents as a Model Context Protocol (MCP) server. By the end of this document, you will be able to start the server, connect it to an AI model, and interact with your agents using an MCP-compatible client like Claude Code. The Model Context Protocol (MCP) is an open standard designed to enable AI assistants to securely connect with various data sources and tools. By exposing AIGNE agents as an MCP server, you can augment MCP-compatible clients with the specialized skills and capabilities of your custom agents. The following diagram illustrates how the AIGNE MCP server connects your agents to an AI model and an MCP-compatible client. ![This guide provides instructions on how to run AIGNE Framework agents as a Model Context Protocol...](https://media.arcblock.io/lib/a1/a11195cfed272271.w1600.webp) ## Prerequisites Before proceeding, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - AI Model Access: An API key for a supported large language model provider, such as OpenAI. ## Quick Start You can run the example directly without a local installation using `npx`. ### 1. Run the MCP Server Execute the following command in your terminal to download and start the MCP server example: **serve-mcp** ```sh npx -y @aigne/example-mcp-server serve-mcp --port 3456 ``` Upon successful execution, the server will start, and you will see the following output, confirming that the MCP server is active and listening for connections. **Expected Output** ```sh Observability OpenTelemetry SDK Started, You can run `npx aigne observe` to start the observability server. MCP server is running on http://localhost:3456/mcp ``` ### 2. Connect to an AI Model The MCP server requires a connection to a large language model to function. If you are running the server for the first time, a command-line prompt will guide you through the connection process. ![A terminal prompt for connecting to an AI model.](https://media.arcblock.io/lib/7a/7a8b39134016fd4c.w1600.webp) You have three primary options for connecting to an AI model: #### Option 1: AIGNE Hub (Recommended) Connect to the official AIGNE Hub to get started quickly. New users receive free credits, making this the most straightforward option for evaluation. Select the first option in the prompt, and your web browser will open to guide you through the authorization process. ![The AIGNE Hub authorization page.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### Option 2: Self-Hosted AIGNE Hub If your organization uses a self-hosted instance of AIGNE Hub, select the second option and enter the URL of your hub instance when prompted. ![A terminal prompt to enter a self-hosted AIGNE Hub URL.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### Option 3: Third-Party Model Provider You can connect directly to a third-party model provider by setting the appropriate environment variables. For example, to use OpenAI, export your API key before running the server command. **Configure OpenAI API Key** ```sh export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After setting the environment variable, restart the `serve-mcp` command. ## Available Agents This example exposes several pre-configured agents as MCP tools, each with a distinct function: - Current Time Agent: Provides the current time. Defined in `agents/current-time.js`. - Poet Agent: Generates poetry and other creative text formats. Defined in `agents/poet.yaml`. - System Info Agent: Retrieves information about the host system. Defined in `agents/system-info.js`. ## Connecting to an MCP Client Once the MCP server is running, you can connect to it from any MCP-compatible client. The following example uses Claude Code. First, ensure you have [Claude Code](https://claude.ai/code) installed. Then, add the AIGNE MCP server as a tool source using the following command: **Add MCP Server to Claude** ```sh claude mcp add -t http test http://localhost:3456/mcp ``` After adding the server, you can invoke the agents' skills directly from the Claude Code interface. ## Observing Agent Execution The AIGNE Framework includes an observability tool that allows you to monitor and debug agent behavior in real-time. This tool is essential for analyzing traces, inspecting inputs and outputs, and understanding agent performance. ### 1. Start the Observer To start the local observability web server, run the following command in a new terminal window: **Start Observability Server** ```sh npx aigne observe --port 7890 ``` The server will start and provide a URL to access the dashboard. ![Terminal output showing the observability server is running.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) ### 2. View Traces Open `http://localhost:7890` in your web browser to access the AIGNE observability dashboard. The "Traces" view provides a list of recent agent executions, including details on latency, token usage, and status. ![The Aigne Observability interface showing a list of traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) --- ## MCP SQLite URL: https://www.arcblock.io/en/docs/aigne-framework/examples-mcp-sqlite-9dc03e/ This guide provides a comprehensive walkthrough for interacting with an SQLite database using an AI agent powered by the AIGNE Framework. By following these steps, you will learn how to set up the necessary components, run the example application, and use an agent to perform database operations like creating tables and querying data. The core of this example involves using an `MCPAgent` to connect to a running [SQLite MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite). This server exposes database functionalities as skills that an `AIAgent` can intelligently invoke based on user prompts. ```d2 direction: down User: { shape: c4-person } App: { label: "@aigne/example-mcp-sqlite" shape: rectangle AIGNE-Framework: { label: "AIGNE Framework (@aigne/core)" shape: rectangle AIGNE-Instance: { label: "AIGNE Instance" } AIAgent: { label: "AIAgent" } MCPAgent: { label: "MCPAgent" } } AI-Model: { label: "AI Model\n(e.g., OpenAI)" shape: rectangle } } SQLite-MCP-Server: { label: "SQLite MCP Server" shape: rectangle } SQLite-DB: { label: "SQLite Database\n(usages.db)" shape: cylinder } User -> App: "1. Run command\n(e.g., 'create a product table')" App.AIGNE-Framework.AIAgent -> App.AI-Model: "2. Interpret prompt" App.AI-Model -> App.AIGNE-Framework.AIAgent: "3. Return required skill call" App.AIGNE-Framework.AIAgent -> App.AIGNE-Framework.MCPAgent: "4. Invoke skill" App.AIGNE-Framework.MCPAgent -> SQLite-MCP-Server: "5. Send command" SQLite-MCP-Server -> SQLite-DB: "6. Execute SQL" SQLite-DB -> SQLite-MCP-Server: "7. Return result" SQLite-MCP-Server -> App.AIGNE-Framework.MCPAgent: "8. Send response" App.AIGNE-Framework.MCPAgent -> App.AIGNE-Framework.AIAgent: "9. Forward response" App.AIGNE-Framework.AIAgent -> App: "10. Process final output" App -> User: "11. Display result message" ``` ## Prerequisites Before proceeding, ensure your development environment meets the following requirements. Adherence to these prerequisites is necessary for the successful execution of the example. - Node.js: Version 20.0 or higher. - npm: Node.js package manager, included with Node.js. - uv: A Python package installer. Required for running the SQLite MCP Server. Installation instructions can be found at the [official `uv` repository](https://github.com/astral-sh/uv). - AI Model API Key: An API key from a supported provider is required for the AI agent to function. This example defaults to OpenAI, but other providers are supported. You can obtain an [OpenAI API key](https://platform.openai.com/api-keys) from their platform. For developers intending to run the example from the source code, the following dependencies are also required: - Pnpm: A fast, disk space-efficient package manager. - Bun: A fast JavaScript all-in-one toolkit used for running tests and examples. ## Quick Start This section provides instructions to run the example directly without a manual installation, which is the most efficient method for a preliminary evaluation. The application can be executed in a one-shot mode for single commands, in an interactive chat mode, or by piping input directly to the script. Execute one of the following commands in your terminal: **Run in one-shot mode (default)** ```bash npx -y @aigne/example-mcp-sqlite ``` **Run in interactive chat mode** ```bash npx -y @aigne/example-mcp-sqlite --interactive ``` **Use pipeline input** ```bash echo "create a product table with columns name description and createdAt" | npx -y @aigne/example-mcp-sqlite ``` ## Connecting to an AI Model The AI agent requires a connection to a Large Language Model (LLM) to process instructions. If you run the example without a pre-configured model, you will be prompted to select a connection method. ![Initial connection prompt when no AI model is configured.](https://media.arcblock.io/lib/05/05a13bf04fd48b70.w1600.webp) There are three primary methods for establishing this connection: ### 1. Connect to the Official AIGNE Hub This is the recommended method for new users. It provides a streamlined, browser-based authentication process. New users receive complimentary credits to test the platform. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your default web browser will open to an authorization page. 3. Follow the on-screen instructions to approve the connection. ![Authorization prompt for connecting the AIGNE CLI to the AIGNE Hub.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) ### 2. Connect to a Self-Hosted AIGNE Hub If your organization operates a private instance of AIGNE Hub, select the second option and provide the URL of your hub to complete the connection. ![Prompt to enter the URL for a self-hosted AIGNE Hub.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) ### 3. Connect via a Third-Party Model Provider You can connect directly to a supported third-party model provider, such as OpenAI, by configuring the appropriate API key as an environment variable. For example, to connect to OpenAI, set the `OPENAI_API_KEY` variable: **Set OpenAI API key** ```bash export OPENAI_API_KEY="your-openai-api-key-here" ``` After setting the environment variable, re-run the `npx` command. For a comprehensive list of supported providers and their required environment variables, refer to the example `.env.local.example` file in the repository. ## Installation from Source For developers who wish to inspect or modify the source code, follow these steps to clone the repository and run the example locally. ### 1. Clone the Repository Clone the official AIGNE Framework repository to your local machine. **Clone the repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the required dependencies using `pnpm`. **Install dependencies** ```bash cd aigne-framework/examples/mcp-sqlite pnpm install ``` ### 3. Run the Example Execute the application using the `pnpm start` command. **Run in one-shot mode (default)** ```bash pnpm start ``` To run in interactive mode or use pipeline input, append the desired flags after a `--` separator. **Run in interactive chat mode** ```bash pnpm start -- --interactive ``` **Use pipeline input** ```bash echo "create a product table with columns name description and createdAt" | pnpm start ``` ### Command-Line Options The application supports several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Enables interactive chat mode. | Disabled (one-shot) | | `--model ` | Specifies the AI model. Format: `'provider[:model]'`. | `openai` | | `--temperature ` | Sets the model's temperature for generation. | Provider default | | `--top-p ` | Sets the model's top-p sampling value. | Provider default | | `--presence-penalty ` | Sets the model's presence penalty. | Provider default | | `--frequency-penalty ` | Sets the model's frequency penalty. | Provider default | | `--log-level ` | Sets the logging verbosity (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input`, `-i ` | Provides input directly as an argument. | `None` | ## Code Example The following TypeScript code demonstrates the core logic for setting up and invoking the AI agent to interact with the SQLite database. The script initializes an `OpenAIChatModel`, starts an `MCPAgent` connected to the SQLite server, and configures an `AIGNE` instance with the model and the agent's skills. Finally, it invokes an `AIAgent` with specific instructions to perform database tasks. **index.ts** ```typescript import { join } from "node:path"; import { AIAgent, AIGNE, MCPAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // 1. Initialize the chat model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // 2. Start the SQLite MCP server as a managed subprocess const sqlite = await MCPAgent.from({ command: "uvx", args: [ "-q", "mcp-server-sqlite", "--db-path", join(process.cwd(), "usages.db"), ], }); // 3. Configure the AIGNE instance with the model and MCP skills const aigne = new AIGNE({ model, skills: [sqlite], }); // 4. Define the AI agent with specific instructions const agent = AIAgent.from({ instructions: "You are a database administrator", }); // 5. Invoke the agent to create a table console.log( await aigne.invoke( agent, "create a product table with columns name description and createdAt", ), ); // Expected output: // { // $message: "The product table has been created successfully with the columns: `name`, `description`, and `createdAt`.", // } // 6. Invoke the agent to insert data console.log(await aigne.invoke(agent, "create 10 products for test")); // Expected output: // { // $message: "I have successfully created 10 test products in the database...", // } // 7. Invoke the agent to query data console.log(await aigne.invoke(agent, "how many products?")); // Expected output: // { // $message: "There are 10 products in the database.", // } // 8. Shut down the AIGNE instance and the MCP server await aigne.shutdown(); ``` ## Debugging To monitor and analyze the agent's execution flow, you can use the `aigne observe` command. This tool launches a local web server that provides a detailed view of traces, tool calls, and model interactions, which is invaluable for debugging and performance analysis. 1. Start the Observation Server: **Start the observability server** ```bash aigne observe ``` ![Terminal output showing the aigne observe command has started the server.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) 2. View Traces: Open the provided URL (e.g., `http://localhost:7893`) in your web browser to access the observability interface. The "Traces" page lists recent agent executions. ![AIGNE observability interface displaying a list of agent execution traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) From here, you can select an individual trace to inspect the complete sequence of operations, including prompts sent to the model, skills invoked by the agent, and the final output. --- ## Memory URL: https://www.arcblock.io/en/docs/aigne-framework/examples-memory-9dc03e/ This guide demonstrates how to build a stateful chatbot that retains conversation history across sessions. By leveraging the `FSMemory` plugin, the agent can persist session data to the local file system, enabling it to recall previous interactions. ## Overview In many conversational AI applications, it is crucial for an agent to remember the context of past interactions to provide coherent and relevant responses. The AIGNE Framework addresses this through its memory components. This example focuses on `FSMemory`, a straightforward solution for persisting conversation history on your local disk. This approach is ideal for development, testing, or applications where state can be managed locally without requiring external databases or services. For more advanced or distributed persistence, consider alternatives like [DIDSpacesMemory](/en/docs/aigne-framework/examples-memory-did-spaces-9dc03e/). ## How to Run the Example You can run this example directly using `npx`. This command will download the necessary packages and execute the chatbot script. To start the chatbot in interactive mode, execute the following command in your terminal: ```sh npx -y @aigne/example-memory --interactive ``` If you have not configured your LLM API keys, you will be prompted to connect to the AIGNE Hub, which provides a simple way to get started. ![Initial connection prompt for the AI model](https://media.arcblock.io/lib/38/387cd4ef36681ee2.w1600.webp) ## Code Explained The core of this example is the integration of the `FSMemory` plugin with an `AIAgent`. The agent is configured to use this memory module to automatically save and retrieve the conversation history for a given session. The following diagram illustrates how the `AIAgent`, `FSMemory` plugin, and the file system interact during a chat session: ![Memory](https://media.arcblock.io/lib/16/161f379787b65017.w1600.webp) ### main.ts The main script initializes the agent, aigneres the memory plugin, and starts the conversational loop. **main.ts** ```typescript import { AIAgent, AIGNE, FSMemory, command, define, option } from '@aigne/framework'; import { ChatOllama } from '@aigne/ollama'; import path from 'node:path'; const program = define({ name: 'memory-chatbot', version: '1.0.0', }); program( command({ name: 'chat', description: 'Chat with the bot', options: [ option({ name: '--interactive', description: 'Chat with the bot', }), ], action: async (_, { session }) => { const memory = new FSMemory({ path: path.join(__dirname, '..', '.memory'), sessionId: session.id, }); const llm = new ChatOllama({ model: 'llama3', }); const chatbot = new AIAgent({ name: 'chatbot', model: llm, memory, instructions: 'Your name is Mega. You are a helpful assistant. Please answer the user question.', }); const aigne = new AIGNE({ agents: [chatbot], }); await aigne.chat(chatbot, { endOfStream: (message) => { if (message.type === 'end') { process.stdout.write('\n'); } if (message.type === 'chunk') { process.stdout.write(message.payload.content); } }, }); }, }) ); program.run(); ``` Key components of the script: 1. Importing Modules: We import `AIAgent`, `AIGNE`, and `FSMemory` from the AIGNE framework. 2. Initializing `FSMemory`: An instance of `FSMemory` is created. 3. - `path`: Specifies the directory (`.memory`) where conversation logs will be stored. - `sessionId`: A unique identifier for the conversation session. This ensures that the history for different chat sessions is stored separately. 4. Configuring `AIAgent`: The `chatbot` agent is instantiated. 5. - `model`: The language model to be used for generating responses. - `memory`: The `FSMemory` instance is passed to the agent's constructor. This links the agent to the persistence layer. - `instructions`: A system prompt that defines the agent's persona and objective. 6. Running the Chat: The `aigne.chat()` method starts the interactive session. The framework automatically handles the loading of past messages from `FSMemory` at the start of the session and saves new messages as the conversation progresses. ## Summary In this example, you have learned how to create a chatbot with persistent memory using the `FSMemory` plugin. This enables the agent to maintain context across multiple interactions by storing and retrieving conversation history from the local file system. This foundational concept is key to building more advanced and context-aware AI applications. --- ## DID Spaces Memory URL: https://www.arcblock.io/en/docs/aigne-framework/examples-memory-did-spaces-9dc03e/ This guide demonstrates how to build a chatbot with persistent memory using DID Spaces. By leveraging the `DIDSpacesMemory` plugin from the AIGNE Framework, your agent can retain conversation history across multiple sessions in a decentralized and secure manner. ## Prerequisites Before you begin, ensure you have the following installed and configured: - Node.js: Version 20.0 or higher. - npm: Included with your Node.js installation. - OpenAI API Key: Required for connecting to the language model. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). - DID Spaces Credentials: Necessary for memory persistence. ## Quick Start You can run this example directly without any local installation using `npx`. ### 1. Run the Example Execute the following command in your terminal: **Run the memory-did-spaces example** ```bash npx -y @aigne/example-memory-did-spaces ``` ### 2. Connect to an AI Model On the first run, the CLI will prompt you to connect to an AI model because no API keys have been configured. ![run-example.png](https://media.arcblock.io/lib/be/be333450dfb435cf.w1600.webp) You have several options to proceed: - Connect via the official AIGNE Hub (Recommended) This is the easiest way to get started. Selecting this option will open your web browser to the official AIGNE Hub authentication page. Follow the on-screen instructions to connect your wallet. New users automatically receive a welcome bonus of 400,000 tokens to use. ![Connect to the official AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) - Connect via a self-hosted AIGNE Hub If you have your own instance of AIGNE Hub, choose this option. You will be prompted to enter the URL of your self-hosted Hub to complete the connection. You can deploy your own AIGNE Hub from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ). ![Connect to a self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) - Connect via a Third-Party Model Provider You can also connect directly to a third-party provider like OpenAI, DeepSeek, or Google Gemini. To do this, you need to set the provider's API key as an environment variable. For example, to use OpenAI, set the `OPENAI_API_KEY` variable: **Set your OpenAI API key here** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After setting the environment variable, run the `npx` command again. ## Local Installation and Execution If you prefer to run the example from the source code, follow these steps. ### 1. Clone the Repository First, clone the AIGNE Framework repository from GitHub: ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and install the required dependencies using `pnpm`: ```bash cd aigne-framework/examples/memory-did-spaces pnpm install ``` ### 3. Run the Example Finally, start the example: ```bash pnpm start ``` The script will execute three tests to demonstrate the memory functionality: storing a user profile, recalling preferences, and creating a portfolio based on the stored data. The results will be displayed in the console and saved to a markdown report file for your review. ## How It Works This example utilizes the `DIDSpacesMemory` plugin from the `@aigne/agent-library` package. This plugin enables the agent to persist conversation history by storing it in DID Spaces, a decentralized personal data storage solution. Key features include: - Decentralized Persistence: Conversations are stored securely in the user's DID Space. - Session Continuity: The chatbot can recall information from previous interactions, even after being restarted. - Privacy and Security: User data is managed using Decentralized Identifier (DID) technology, ensuring privacy and user control. The example showcases this by storing user profile details, recalling them in a new interaction, and using that remembered context to provide personalized recommendations. ## Configuration While the example comes with a pre-configured DID Spaces endpoint for demonstration purposes, you will need to update the configuration for a production application. This involves setting up your own DID Spaces instance and providing the correct URL and authentication credentials in the code. **memory-config.ts** ```typescript import { DIDSpacesMemory } from '@aigne/agent-library'; const memory = new DIDSpacesMemory({ url: "YOUR_DID_SPACES_URL", auth: { authorization: "Bearer YOUR_TOKEN", }, }); ``` Replace `"YOUR_DID_SPACES_URL"` and `"Bearer YOUR_TOKEN"` with your actual endpoint and authentication token. ## Debugging with AIGNE Observe To monitor and debug your agent's execution, you can use the `aigne observe` command. This tool launches a local web server that provides a detailed view of agent traces, helping you understand its behavior, diagnose issues, and optimize performance. To start the observation server, run: ```bash aigne observe ``` ![AIGNE Observe server starting](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) Once running, you can open the provided URL (`http://localhost:7893` by default) in your browser to view a list of recent agent executions and inspect their details. ![AIGNE Observe trace list](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This example has demonstrated how to integrate decentralized, persistent memory into an AI agent using the `DIDSpacesMemory` plugin. This capability allows you to create more sophisticated and context-aware chatbots that remember user interactions across sessions. To learn more about related concepts, refer to the following documentation: ::::card-group ::link-card{title="Memory" description="Learn about the core concepts of agent memory in the AIGNE Framework." icon="brain" href="/en/docs/aigne-framework/developer-guide-core-concepts-memory-9dc03e/"} ::link-card{title="File System Memory" description="Explore another example that uses the local file system for memory persistence." icon="folder" href="/en/docs/aigne-framework/examples-memory-9dc03e/"} :::: --- ## Nano Banana URL: https://www.arcblock.io/en/docs/aigne-framework/examples-nano-banana-9dc03e/ This guide demonstrates how to build and run a chatbot capable of generating images. By following these steps, you will learn how to execute a pre-built AIGNE example, connect it to an AI model, and inspect its behavior using the framework's observability tools. ## Prerequisites Before proceeding, ensure the following requirements are met: - Node.js: Version 20.0 or higher must be installed. You can download it from [nodejs.org](https://nodejs.org). - OpenAI API Key: An API key from [OpenAI](https://platform.openai.com/api-keys) is required to interact with their image generation models. ## Quick Start You can run this example directly without a local installation using `npx`. ### Run the Example Execute the following command in your terminal to run the chatbot with a single input. This command will download and run the example package. **Run with a single input** ```bash npx -y @aigne/example-nano-banana --input 'Draw an image of a lovely cat' ``` To start an interactive session where you can have a conversation with the chatbot, use the `--interactive` flag. **Run in interactive mode** ```bash npx -y @aigne/example-nano-banana --interactive ``` ### Connect to an AI Model On the first run, the application will detect that no AI model is configured and will prompt you to connect one. ![Initial setup prompt for connecting an AI model.](https://media.arcblock.io/lib/3b/3b507241ce7423c3.w1600.webp) You have three primary options to connect to an AI model: #### 1. Connect via the Official AIGNE Hub (Recommended) This is the simplest method. Choosing this option will open your web browser and guide you through the authorization process on the official AIGNE Hub. New users receive a complimentary token allocation to get started immediately. ![AIGNE Hub authorization screen.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### 2. Connect via a Self-Hosted AIGNE Hub If you operate your own instance of AIGNE Hub, select this option. You will be prompted to enter the URL of your self-hosted Hub to complete the connection. You can deploy your own AIGNE Hub from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ). ![Prompt to enter the URL for a self-hosted AIGNE Hub.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### 3. Connect via a Third-Party Model Provider You can directly connect to a third-party provider like OpenAI by configuring the necessary API key as an environment variable. For example, to use OpenAI, set the `OPENAI_API_KEY` variable in your terminal. **Set OpenAI API key** ```bash export OPENAI_API_KEY="your-openai-api-key-here" ``` After setting the environment variable, run the `npx` command again. For a comprehensive list of supported variables for different model providers, refer to the example environment file in the source repository. ### Debugging with the Observability UI The AIGNE Framework includes a built-in observability tool to help you monitor and debug your agents. The `aigne observe` command launches a local web server that provides a detailed view of agent execution traces. First, start the observation server by running the following command in your terminal: **Start the observability server** ```bash aigne observe ``` ![Terminal output showing the aigne observe command successfully starting the server.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) Once the server is running, you can open the provided URL (typically `http://localhost:7893`) in your browser to view a list of recent agent executions. This interface allows you to inspect the inputs, outputs, latency, and token usage for each trace, providing critical insights for debugging and optimization. ![The AIGNE observability UI showing a list of agent execution traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Local Installation and Execution For development purposes, you may prefer to clone the repository and run the example locally. ### 1. Clone the Repository Clone the official AIGNE Framework repository from GitHub. **Clone the repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and install the required dependencies using `pnpm`. **Install dependencies** ```bash cd aigne-framework/examples/nano-banana pnpm install ``` ### 3. Run the Example After the installation is complete, you can run the example using the `start` script defined in the project's `package.json`. **Run the local example** ```bash pnpm start ``` ## Summary This document provided a step-by-step guide to running the "Nano Banana" example, which demonstrates an AI chatbot with image generation capabilities. You have learned how to execute the example directly with `npx`, connect various AI model providers, and use the `aigne observe` command to debug agent behavior. For more advanced use cases and a deeper understanding of the framework's capabilities, please refer to the following sections: ::::card-group ::link-card{title="Image Agent" description="Learn how to configure and use agents for image generation." icon="image" href="/en/docs/aigne-framework/developer-guide-agents-image-agent-9dc03e/"} ::link-card{title="AI Agent" description="Explore the primary agent for interacting with language models." icon="bot" href="/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/"} :::: --- ## Workflow Code Execution URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-code-execution-9dc03e/ Executing dynamically generated code from an AI model presents significant security and reliability challenges. This guide provides a structured, step-by-step process for building a secure code execution workflow using the AIGNE Framework. You will learn how to orchestrate a `Coder` agent, which generates code, and a `Sandbox` agent, which executes it in an isolated environment. ## Overview The code execution workflow is designed to safely handle tasks that require dynamic code generation and execution. It employs a two-agent system: ::::steps :::step{title="Coder Agent"} An AI-driven agent responsible for interpreting a user's request and writing the necessary JavaScript code to solve it. ::: :::step{title="Sandbox Agent"} A `FunctionAgent` that takes the generated code and executes it in a controlled environment, returning the result. ::: :::: This separation of concerns ensures that the AI's code generation is isolated from direct execution, providing a layer of security. ### Logical Flow The following diagram illustrates the high-level interaction between the agents. The `Coder` agent receives an input, generates code, passes it to the `Sandbox` for execution, and then formats the final output. ```d2 direction: down User-Input: { label: "User Input\n(e.g., 'Calculate 15!')" shape: rectangle } AIGNE-Framework: { label: "AIGNE Framework" shape: rectangle Coder-Agent: { label: "Coder Agent\n(AIAgent)" shape: rectangle } Sandbox-Agent: { label: "Sandbox Agent\n(FunctionAgent)" shape: rectangle } } Final-Output: { label: "Final Output" shape: rectangle } User-Input -> AIGNE-Framework.Coder-Agent: "1. Receives prompt" AIGNE-Framework.Coder-Agent -> AIGNE-Framework.Sandbox-Agent: "2. Generates JS code & passes for execution" AIGNE-Framework.Sandbox-Agent -> AIGNE-Framework.Coder-Agent: "3. Executes code & returns result" AIGNE-Framework.Coder-Agent -> Final-Output: "4. Formats final response" ``` ### Sequence of Interaction This sequence diagram details the turn-by-turn communication between the user and the agents for a specific task, such as calculating a factorial. ## Quick Start You can run this example directly without any local installation using `npx`. ### Run the Example The example supports a one-shot execution mode for single tasks and an interactive chat mode for conversational workflows. #### One-Shot Mode This is the default mode. The agent processes a single input and exits. ```bash npx -y @aigne/example-workflow-code-execution ``` You can also provide input directly via standard input pipeline. ```bash echo 'Calculate 15!' | npx -y @aigne/example-workflow-code-execution ``` #### Interactive Chat Mode Use the `--interactive` flag to start a persistent session where you can have a conversation with the agent. ```bash npx -y @aigne/example-workflow-code-execution --interactive ``` ### Connect to an AI Model The first time you run the example, it will prompt you to connect to a Large Language Model (LLM) since one is required for the `Coder` agent to function. You have several options to proceed. #### Option 1: AIGNE Hub (Recommended) This is the easiest way to get started. The official AIGNE Hub provides free credits for new users. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your web browser will open an authorization page. 3. Follow the prompts to approve the connection. #### Option 2: Self-Hosted AIGNE Hub If you have your own instance of AIGNE Hub, you can connect to it. 1. Select the second option: `Connect to a self-hosted AIGNE Hub`. 2. You will be prompted to enter the URL of your AIGNE Hub instance. #### Option 3: Third-Party Model Providers You can connect directly to a third-party model provider like OpenAI, Anthropic, or Google Gemini by setting the appropriate environment variables. For example, to use OpenAI, set your API key: ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After setting the environment variable, run the example command again. For a list of all supported providers and their required environment variables, refer to the example `.env.local.example` file. ### Debugging with AIGNE Observe The AIGNE Framework includes a powerful observability tool for debugging and analyzing agent behavior. 1. Start the Server: In your terminal, run the `aigne observe` command. This launches a local web server. ```bash aigne observe ``` 2. View Traces: Open your web browser and navigate to the local URL provided (e.g., `http://localhost:7893`). The interface displays a list of recent agent executions, allowing you to inspect inputs, outputs, tool calls, and performance metrics for each trace. ## Local Installation and Usage For development purposes, you can clone the repository and run the example locally. ### Prerequisites - [Node.js](https://nodejs.org) (version 20.0 or higher) - [pnpm](https://pnpm.io) for package management ### 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the required packages. ```bash cd aigne-framework/examples/workflow-code-execution pnpm install ``` ### 3. Run the Example Use the `pnpm start` command to execute the workflow. ```bash # Run in one-shot mode (default) pnpm start # Run in interactive chat mode pnpm start -- --interactive # Use pipeline input echo "Calculate 15!" | pnpm start ``` ### Command-Line Options The script accepts several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | Specify the AI model to use, e.g., `openai` or `openai:gpt-4o-mini`. | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input`, `-i ` | Provide input directly as an argument. | None | #### Usage Example This command runs the workflow in interactive mode with the `DEBUG` log level. ```bash pnpm start -- --interactive --log-level DEBUG ``` ## Code Implementation The following TypeScript code demonstrates how to construct the code execution workflow. It defines the `sandbox` and `coder` agents and invokes them using the AIGNE instance. **index.ts** ```typescript import { AIAgent, AIGNE, FunctionAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; import { z } from "zod"; // Retrieve the OpenAI API key from environment variables. const { OPENAI_API_KEY } = process.env; // 1. Initialize the Chat Model // This model will power the AI agent. const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // 2. Define the Sandbox Agent // This agent safely executes JavaScript code using a FunctionAgent. const sandbox = FunctionAgent.from({ name: "evaluateJs", description: "A js sandbox for running javascript code", inputSchema: z.object({ code: z.string().describe("The code to run"), }), process: async (input: { code: string }) => { const { code } = input; // The use of eval is isolated within this sandboxed agent. // biome-ignore lint/security/noGlobalEval: const result = eval(code); return { result }; }, }); // 3. Define the Coder Agent // This AI agent is instructed to write code and use the sandbox skill. const coder = AIAgent.from({ name: "coder", instructions: `\ You are a proficient coder. You write code to solve problems. Work with the sandbox to execute your code. `, skills: [sandbox], }); // 4. Initialize the AIGNE Framework const aigne = new AIGNE({ model }); // 5. Invoke the Workflow // The AIGNE instance runs the coder agent with the user's prompt. const result = await aigne.invoke(coder, "10! = ?"); console.log(result); // Expected Output: // { // $message: "The value of \\(10!\\) (10 factorial) is 3,628,800.", // } ``` ## Summary This guide has demonstrated how to build and run a secure code execution workflow using the AIGNE Framework. By separating the concerns of code generation and execution into distinct `AIAgent` and `FunctionAgent` roles, you can safely leverage the power of LLMs for tasks that require dynamic code. For more advanced workflow patterns, explore the following examples: ::::card-group ::link-card{title="Sequential Workflow" description="Build step-by-step processing pipelines with guaranteed execution order." icon="arrow-right" href="/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/"} ::link-card{title="Workflow Orchestration" description="Coordinate multiple agents working together in sophisticated processing pipelines." icon="flag" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Workflow Concurrency URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-concurrency-9dc03e/ Executing tasks in parallel can significantly improve the efficiency of complex workflows. This guide demonstrates how to build a concurrent workflow using the AIGNE Framework, where multiple agents process the same input simultaneously, and their outputs are aggregated. You will learn how to set up and run a practical example that analyzes a product from different perspectives at the same time. ## Overview In this example, we will construct a workflow that takes a product description as input. Two specialized agents will then work in parallel: ::::steps :::step{title="Feature Extractor"} Analyzes the description to identify and summarize key product features. ::: :::step{title="Audience Analyzer"} Analyzes the same description to determine the target audience. ::: :::: Finally, an Aggregator combines the outputs from both agents into a single, consolidated result. This parallel processing model is ideal for tasks that can be broken down into independent sub-tasks, reducing the total execution time. The diagram below illustrates this concurrent workflow: ```d2 direction: down Input: { label: "Product Description" shape: oval } Parallel-Processing: { label: "Parallel Processing" style.stroke-dash: 2 Feature-Extractor: { label: "Feature Extractor\n(Agent 1)" } Audience-Analyzer: { label: "Audience Analyzer\n(Agent 2)" } } Aggregator: { label: "Aggregator" } Result: { label: "Consolidated Result" shape: oval } Input -> Parallel-Processing.Feature-Extractor: "Analyzes features" Input -> Parallel-Processing.Audience-Analyzer: "Analyzes audience" Parallel-Processing.Feature-Extractor -> Aggregator: "Feature summary" Parallel-Processing.Audience-Analyzer -> Aggregator: "Audience profile" Aggregator -> Result ``` ## Prerequisites Before proceeding, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Included with Node.js. - OpenAI API Key: Required for connecting to OpenAI models. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). ## Quick Start You can run this example directly without any installation using `npx`. ### Run the Example Execute the following commands in your terminal to run the workflow in different modes. - One-Shot Mode (Default): Processes a single, predefined input and exits. ```bash npx -y @aigne/example-workflow-concurrency ``` - Interactive Chat Mode: Starts a chat session where you can provide multiple inputs. ```bash npx -y @aigne/example-workflow-concurrency --interactive ``` - Pipeline Mode: Uses input piped from another command. ```bash echo "Analyze product: Smart home assistant with voice control and AI learning capabilities" | npx -y @aigne/example-workflow-concurrency ``` ### Connect to an AI Model The first time you run the example, you will be prompted to connect to an AI model provider, as no API keys have been configured. ![Initial connection prompt for AI model setup](https://media.arcblock.io/lib/96/96938661648993fc.w1600.webp) You have several options to proceed: 1. Connect via the official AIGNE Hub (Recommended) This is the easiest way to get started. New users receive free credits. Select the first option, and your browser will open to the AIGNE Hub authorization page. Follow the on-screen instructions to approve the connection. ![Authorize AIGNE CLI to connect to AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) 2. Connect via a self-hosted AIGNE Hub If you have your own AIGNE Hub instance, choose the second option. You will be prompted to enter the URL of your self-hosted Hub to complete the connection. ![Enter the URL for a self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) 3. Connect via a Third-Party Model Provider You can connect directly to a provider like OpenAI by setting an environment variable with your API key. For example, to use OpenAI, export your key and re-run the command: ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" npx -y @aigne/example-workflow-concurrency --interactive ``` ## Installation from Source For development or customization, you can clone the repository and run the example locally. ### 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and install the required packages using pnpm. ```bash cd aigne-framework/examples/workflow-concurrency pnpm install ``` ### 3. Run the Example Use the `pnpm start` command to execute the workflow. Command-line arguments must be passed after `--`. - Run in one-shot mode: ```bash pnpm start ``` - Run in interactive chat mode: ```bash pnpm start -- --interactive ``` - Use pipeline input: ```bash echo "Analyze product: Smart home assistant with voice control and AI learning capabilities" | pnpm start ``` ## Run Options The application supports several command-line parameters for customization: | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled (one-shot mode) | | `--model ` | Specify the AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input`, `-i ` | Specify input directly via the command line. | None | ## Code Example The following TypeScript code demonstrates how to define and orchestrate the concurrent workflow using `TeamAgent` with `ProcessMode.parallel`. **concurrency-workflow.ts** ```typescript import { AIAgent, AIGNE, ProcessMode, TeamAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // Initialize the AI model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // Define the first agent to extract product features const featureExtractor = AIAgent.from({ instructions: `\ You are a product analyst. Extract and summarize the key features of the product.\n\nProduct description:\n{{product}}`, outputKey: "features", }); // Define the second agent to analyze the target audience const audienceAnalyzer = AIAgent.from({ instructions: `\ You are a market researcher. Identify the target audience for the product.\n\nProduct description:\n{{product}}`, outputKey: "audience", }); // Initialize the AIGNE instance const aigne = new AIGNE({ model }); // Create a TeamAgent to manage the parallel workflow const teamAgent = TeamAgent.from({ skills: [featureExtractor, audienceAnalyzer], mode: ProcessMode.parallel, }); // Invoke the team with a product description const result = await aigne.invoke(teamAgent, { product: "AIGNE is a No-code Generative AI Apps Engine", }); console.log(result); /* Expected Output: { features: "**Product Name:** AIGNE\n\n**Product Type:** No-code Generative AI Apps Engine\n\n...", audience: "**Small to Medium Enterprises (SMEs)**: \n - Businesses that may not have extensive IT resources or budget for app development but are looking to leverage AI to enhance their operations or customer engagement.\n\n...", } */ ``` ## Debugging The AIGNE Framework includes a built-in observability tool to help you monitor and debug agent executions. Start the observability server by running: ```bash aigne observe ``` ![Terminal output showing the aigne observe command running](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) This command starts a local web server, typically at `http://localhost:7893`. Open this URL in your browser to access the observability interface, where you can inspect detailed traces of each agent's execution, including inputs, outputs, and performance metrics. ![Aigne Observability interface showing a list of recent traces](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This guide covered how to create and run a concurrent workflow using the AIGNE Framework. By leveraging `TeamAgent` in parallel mode, you can efficiently process multiple independent tasks simultaneously. To explore other workflow patterns, see the following examples: ::::card-group ::link-card{title="Sequential Workflow" description="Learn how to execute agents in a specific, ordered sequence." icon="arrow-right" href="/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/"} ::link-card{title="Workflow Orchestration" description="Coordinate multiple agents in more complex, sophisticated pipelines." icon="flag" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Workflow Group Chat URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-group-chat-9dc03e/ This guide demonstrates how to build and run a multi-agent group chat workflow using the AIGNE Framework. You will learn how to orchestrate several agents, including a manager, to collaborate on a task, simulating a team environment where they share messages and work together to achieve a common goal. ## Overview The Group Chat workflow example showcases a sophisticated multi-agent system where different agents with specialized roles collaborate to fulfill a user's request. The process is managed by a `Group Manager` agent that directs the conversation and task execution among other agents like a `Writer`, `Editor`, and `Illustrator`. This example supports two primary modes of operation: - One-shot mode: The workflow runs once to completion based on a single input. - Interactive mode: The workflow engages in a continuous conversation, allowing for follow-up questions and dynamic interactions. The core interaction model is as follows: ```d2 direction: down User: { shape: c4-person } GroupChat: { label: "Group Chat Workflow" shape: rectangle Group-Manager: { label: "Group Manager" shape: rectangle } Collaborators: { label: "Collaborators" shape: rectangle grid-columns: 3 Writer: { shape: rectangle } Editor: { shape: rectangle } Illustrator: { shape: rectangle } } } User -> GroupChat.Group-Manager: "1. User Request" GroupChat.Group-Manager -> GroupChat.Collaborators.Writer: "2. Delegate Task" GroupChat.Collaborators.Writer <-> GroupChat.Collaborators.Editor: "3. Collaborate" GroupChat.Collaborators.Editor <-> GroupChat.Collaborators.Illustrator: "4. Collaborate" GroupChat.Collaborators.Writer -> GroupChat.Group-Manager: "5. Send Result" GroupChat.Group-Manager -> User: "6. Final Output" ``` ## Prerequisites Before proceeding, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Included with Node.js. - OpenAI API Key: Required for the default model configuration. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). ## Quick Start You can run this example directly without cloning the repository using `npx`. ### Run the Example Execute one of the following commands in your terminal: To run the workflow in the default one-shot mode: **Run in one-shot mode** ```bash npx -y @aigne/example-workflow-group-chat ``` To start an interactive chat session: **Run in interactive mode** ```bash npx -y @aigne/example-workflow-group-chat --interactive ``` You can also provide input directly via a pipeline: **Run with pipeline input** ```bash echo "Write a short story about space exploration" | npx -y @aigne/example-workflow-group-chat ``` ### Connect to an AI Model The first time you run the example, it will prompt you to connect to an AI model provider since no API keys have been configured. ![Initial setup prompt for connecting to an AI model.](https://media.arcblock.io/lib/b5/b547e1eb5cde9c69.w1600.webp) You have several options to proceed: #### 1. Connect to the AIGNE Hub (Recommended) This is the easiest way to get started and includes free credits for new users. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your web browser will open a page to authorize the AIGNE CLI. 3. Click "Approve" to grant the necessary permissions. The CLI will be configured automatically. ![Authorization dialog for AIGNE Hub connection.](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### 2. Connect to a Self-Hosted AIGNE Hub If you are running your own instance of AIGNE Hub: 1. Select the second option: `Connect to your self-hosted AIGNE Hub`. 2. Enter the URL of your AIGNE Hub instance when prompted. 3. Follow the instructions in your browser to complete the connection. ![Prompt to enter the URL for a self-hosted AIGNE Hub.](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### 3. Configure a Third-Party Model Provider You can directly connect to a provider like OpenAI by setting an environment variable. 1. Exit the interactive prompt. 2. Set the `OPENAI_API_KEY` environment variable in your terminal: **Configure OpenAI API Key** ```bash export OPENAI_API_KEY="your-openai-api-key" ``` 3. Run the example command again. For other providers like Google Gemini or DeepSeek, refer to the `.env.local.example` file within the project for the correct environment variable names. ## Local Installation and Usage For development purposes, you can clone the repository and run the example locally. ### 1. Clone the Repository **Clone the framework repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and install the required packages using `pnpm`. **Install dependencies** ```bash cd aigne-framework/examples/workflow-group-chat pnpm install ``` ### 3. Run the Example Use the `pnpm start` command to run the workflow. Command-line arguments must be passed after `--`. To run in one-shot mode: **Run in one-shot mode** ```bash pnpm start ``` To run in interactive chat mode: **Run in interactive mode** ```bash pnpm start -- --interactive ``` To use pipeline input: **Run with pipeline input** ```bash echo "Write a short story about space exploration" | pnpm start ``` ### Command-Line Options The example accepts several command-line arguments to customize its behavior: | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode | Disabled (one-shot mode) | | `--model ` | AI model to use in format 'provider[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini' | openai | | `--temperature ` | Temperature for model generation | Provider default | | `--top-p ` | Top-p sampling value | Provider default | | `--presence-penalty ` | Presence penalty value | Provider default | | `--frequency-penalty ` | Frequency penalty value | Provider default | | `--log-level ` | Set logging level (ERROR, WARN, INFO, DEBUG, TRACE) | INFO | | `--input`, `-i ` | Specify input directly | None | #### Examples **Set logging level** ```bash pnpm start -- --log-level DEBUG ``` **Use a specific model** ```bash pnpm start -- --model openai:gpt-4o-mini ``` ## Debugging with AIGNE Observe To inspect the execution flow and debug the behavior of the agents, you can use the `aigne observe` command. This tool launches a local web server that provides a detailed view of agent traces. First, start the observability server in a separate terminal: **Start the observability server** ```bash aigne observe ``` ![Terminal output showing the AIGNE Observe server starting.](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) After running the workflow example, open your browser to `http://localhost:7893` to view the traces. You can inspect the inputs, outputs, and internal states of each agent throughout the execution. ![AIGNE Observe web interface showing a list of traces.](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This guide provided a step-by-step walkthrough for running the Workflow Group Chat example. You learned how to execute the workflow using `npx`, connect to various AI model providers, and install it locally for development. You also saw how to use `aigne observe` for debugging agent interactions. For more complex patterns, explore other examples in the AIGNE Framework documentation. ::::card-group ::link-card{title="Workflow: Handoff" description="Learn how to create seamless transitions between specialized agents to solve complex problems." icon="refresh" href="/en/docs/aigne-framework/examples-workflow-handoff-9dc03e/"} ::link-card{title="Workflow: Orchestration" description="Discover how to coordinate multiple agents working together in sophisticated processing pipelines." icon="routes" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Workflow Handoff URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-handoff-9dc03e/ This guide demonstrates how to build a workflow where one agent can seamlessly hand off control to another specialized agent. By the end, you will understand how to create multi-agent systems that delegate tasks based on user input, enabling more complex and dynamic problem-solving. ## Overview In many sophisticated AI applications, a single agent may not possess all the necessary skills to handle a wide range of tasks. The workflow handoff pattern addresses this by allowing a primary agent to act as a dispatcher, transferring control to a specialized agent when a specific trigger or condition is met. This creates a seamless transition, enabling different agents to collaborate on solving a complex problem. This example implements a simple handoff: - Agent A: A general-purpose agent. - Agent B: A specialized agent that only communicates in Haikus. When the user instructs Agent A to "transfer to agent b," the system seamlessly hands off the conversation to Agent B for all subsequent interactions. ```d2 shape: sequence_diagram User: { shape: c4-person } AIGNE-Framework: { label: "AIGNE Framework" } Agent-A: { label: "Agent A\n(General Purpose)" } Agent-B: { label: "Agent B\n(Haiku Specialist)" } User -> AIGNE-Framework: "1. 'transfer to agent b'" AIGNE-Framework -> Agent-A: "2. Invoke with input" Agent-A -> Agent-A: "3. Execute skill: transfer_to_b()" Agent-A -> AIGNE-Framework: "4. Return Agent B object" AIGNE-Framework -> AIGNE-Framework: "5. Handoff: Replace Agent A with B" AIGNE-Framework -> Agent-B: "6. Invoke Agent B for response" Agent-B -> AIGNE-Framework: "7. Generate Haiku response" AIGNE-Framework -> User: "8. Display Agent B's response" User -> AIGNE-Framework: "9. 'It's a beautiful day'" AIGNE-Framework -> Agent-B: "10. Invoke with new input" Agent-B -> AIGNE-Framework: "11. Generate another Haiku" AIGNE-Framework -> User: "12. Display Agent B's response" ``` ## Prerequisites Before running the example, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Comes bundled with Node.js. - AI Model Provider Account: An API key from a provider like OpenAI is required to power the agents. ## Quick Start You can run this example directly without cloning the repository using `npx`. ### Step 1: Run the Example Open your terminal and execute one of the following commands. The `--interactive` flag enables an interactive session where you can have a continuous conversation. **Run in one-shot mode** ```bash npx -y @aigne/example-workflow-handoff ``` **Run in interactive chat mode** ```bash npx -y @aigne/example-workflow-handoff --interactive ``` You can also pipe input directly into the command: **Use pipeline input** ```bash echo "transfer to agent b" | npx -y @aigne/example-workflow-handoff ``` ### Step 2: Connect to an AI Model If you are running the example for the first time, you will be prompted to connect to an AI model, as no API keys have been configured. ![run example](https://media.arcblock.io/lib/03/036c470831dc238a.w1600.webp) You have several options to proceed: 1. Connect to the AIGNE Hub (Recommended) This is the easiest way to get started. The official AIGNE Hub provides free credits for new users. Select the first option, and your browser will open a page to authorize the connection. ![connect to official aigne hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) 2. Connect to a Self-Hosted AIGNE Hub If you have your own instance of AIGNE Hub, choose the second option and enter its URL to connect. ![connect to self hosted aigne hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) 3. Configure a Third-Party Model Provider You can connect directly to a provider like OpenAI, DeepSeek, or Google Gemini by setting the appropriate environment variables. For example, to use OpenAI, set your API key in the terminal: **Configure OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` After configuring the environment variable, run the `npx` command again. ## Code Deep Dive The core of this example is a function that acts as a "skill" for the first agent. When the model determines that this skill should be used based on the user's input, the function returns a new agent, effectively transferring control. ### How It Works ::::steps :::step{title="Agent A (Dispatcher):"} This agent is configured with a `transfer_to_b` skill. Its instructions are general. ::: :::step{title="Agent B (Specialist):"} This agent has a very specific instruction: "Only speak in Haikus." It has no special skills. ::: :::step{title="The Handoff Mechanism:"} The `transfer_to_b` function simply returns the `agentB` object. When the AIGNE Framework receives an agent object as the result of a skill execution, it replaces the current agent in the session with the new one. ::: :::: ### Example Implementation The following code demonstrates how to define two agents and implement the handoff logic. **index.ts** ```typescript import { AIAgent, AIGNE } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // 1. Initialize the AI Model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // 2. Define the skill that performs the handoff function transfer_to_b() { return agentB; } // 3. Define Agent A with the handoff skill const agentA = AIAgent.from({ name: "AgentA", instructions: "You are a helpful agent.", outputKey: "A", skills: [transfer_to_b], }); // 4. Define Agent B, the specialist const agentB = AIAgent.from({ name: "AgentB", instructions: "Only speak in Haikus.", outputKey: "B", }); // 5. Initialize the AIGNE runtime const aigne = new AIGNE({ model }); // 6. Start the session with Agent A const userAgent = aigne.invoke(agentA); // 7. First invocation: Trigger the handoff const result1 = await userAgent.invoke("transfer to agent b"); console.log(result1); // Expected Output: // { // B: "Transfer now complete, \nAgent B is here to help. \nWhat do you need, friend?", // } // 8. Second invocation: Now talking to Agent B const result2 = await userAgent.invoke("It's a beautiful day"); console.log(result2); // Expected Output: // { // B: "Sunshine warms the earth, \nGentle breeze whispers softly, \nNature sings with joy. ", // } ``` ## Running from Source (Optional) If you wish to modify or inspect the code locally, follow these steps. ### 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the necessary packages using `pnpm`. ```bash cd aigne-framework/examples/workflow-handoff pnpm install ``` ### 3. Run the Example Use the `pnpm start` command. To pass additional arguments like `--interactive`, add an extra `--` before them. **Run in one-shot mode** ```bash pnpm start ``` **Run in interactive chat mode** ```bash pnpm start -- --interactive ``` ## Command-Line Options The example script accepts several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Temperature for model generation. | Provider default | | `--top-p ` | Top-p sampling value. | Provider default | | `--presence-penalty ` | Presence penalty value. | Provider default | | `--frequency-penalty ` | Frequency penalty value. | Provider default | | `--log-level ` | Set logging level (ERROR, WARN, INFO, DEBUG, TRACE). | INFO | | `--input`, `-i ` | Specify input directly via the command line. | None | ## Debugging and Observation To inspect the agent's execution flow, you can use the `aigne observe` command. This tool launches a local web server that provides a detailed view of traces, calls, and other runtime data, which is invaluable for debugging. First, start the observation server in a separate terminal: **Start the observation server** ```bash aigne observe ``` ![aigne-observe-execute](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) After running the example, you can view the execution traces in the web interface, which is typically available at `http://localhost:7893`. ![aigne-observe-list](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary You have now learned how to implement a workflow handoff, a powerful pattern for building multi-agent systems where tasks are delegated to specialized agents. This approach allows you to construct more robust and capable AI applications by composing agents with distinct skills. To explore more advanced agent orchestration, check out these related examples: ::::card-group ::link-card{title="Workflow Orchestration" description="Coordinate multiple agents working together in sophisticated processing pipelines." icon="flag" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} ::link-card{title="Workflow Router" description="Implement intelligent routing logic to direct requests to appropriate handlers based on content." icon="git-branch" href="/en/docs/aigne-framework/examples-workflow-router-9dc03e/"} :::: --- ## Workflow Orchestration URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/ This guide demonstrates how to build and run a sophisticated workflow that orchestrates multiple specialized AI agents. You will learn to coordinate agents like a `finder`, `writer`, and `proofreader` to work together on a complex task, from initial research to final report generation. ## Overview Workflow orchestration involves creating a processing pipeline where multiple agents collaborate to achieve a common goal. Each agent in the pipeline has a specific role, and a central orchestrator manages the flow of tasks and information between them. This example showcases how to use the AIGNE Framework to build such a system, supporting both single-run (one-shot) and interactive chat modes. The following diagram illustrates the agent relationships in this example: ```d2 direction: down User: { shape: c4-person } OrchestratorAgent: { label: "Orchestrator Agent" shape: rectangle finder: { label: "Finder Agent" shape: rectangle } writer: { label: "Writer Agent" shape: rectangle } } Skills: { label: "Skills / Tools" shape: rectangle style: { stroke-dash: 2 } puppeteer: { label: "Puppeteer\n(Web Scraping)" shape: rectangle } filesystem: { label: "Filesystem\n(Read/Write)" shape: cylinder } } User -> OrchestratorAgent: "1. Submits research task" OrchestratorAgent -> OrchestratorAgent.finder: "2. Delegate: Find info" OrchestratorAgent.finder -> Skills.puppeteer: "3. Scrape web" OrchestratorAgent.finder -> Skills.filesystem: "4. Save findings" OrchestratorAgent -> OrchestratorAgent.writer: "5. Delegate: Compile report" OrchestratorAgent.writer -> Skills.filesystem: "6. Write final report" ``` ## Prerequisites Before you begin, ensure you have the following installed and configured: - Node.js: Version 20.0 or higher. - npm: Comes bundled with Node.js. - OpenAI API Key: Required for the agents to interact with OpenAI models. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). Optional dependencies for running from source code: - Bun: For running unit tests and examples. - Pnpm: For package management. ## Quick Start You can run this example directly without any installation using `npx`. ### Run the Example Execute the following commands in your terminal: **Run in one-shot mode** ```bash # Run in one-shot mode (default) npx -y @aigne/example-workflow-orchestrator ``` **Run in interactive chat mode** ```bash # Run in interactive chat mode npx -y @aigne/example-workflow-orchestrator --interactive ``` **Use pipeline input** ```bash # Use pipeline input echo "Research ArcBlock and compile a report about their products and architecture" | npx -y @aigne/example-workflow-orchestrator ``` ### Connect to an AI Model The first time you run the example, it will prompt you to connect to an AI model service since no API keys have been configured. ![Initial prompt to connect an AI model](https://media.arcblock.io/lib/ce/ce107f134436a7c8.w1600.webp) You have three options: 1. Connect via the Official AIGNE Hub: This is the recommended option for new users. Selecting it will open your browser to an authorization page. After you approve, the CLI will be connected to the AIGNE Hub, and you'll receive complimentary tokens to get started. ![Authorize connection to the official AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) 2. Connect via a Self-Hosted AIGNE Hub: Choose this if you have your own AIGNE Hub instance. You will be prompted to enter the URL of your hub to complete the connection. You can deploy a self-hosted AIGNE Hub from the [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ). ![Enter the URL for a self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) 3. Connect via a Third-Party Model Provider: You can configure an API key from a provider like OpenAI directly. Set the key as an environment variable and run the example again. **Set OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_API_KEY_HERE" ``` For more configuration examples, refer to the `.env.local.example` file in the repository. ### Debugging with AIGNE Observe The `aigne observe` command launches a local web server that helps you monitor and analyze agent executions. This tool is invaluable for debugging, tuning performance, and understanding agent behavior. First, start the observation server: **Start the observability server** ```bash aigne observe ``` ![Terminal output showing the observability server running](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) Once the server is running, you can open the provided URL (`http://localhost:7893`) in your browser to view a list of recent agent traces and inspect their details. ![AIGNE Observe web interface showing a list of traces](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Local Installation and Usage For development purposes, you can clone the repository and run the example locally. ### 1. Clone the Repository **Clone the repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example directory and install the necessary packages using `pnpm`. **Install dependencies** ```bash cd aigne-framework/examples/workflow-orchestrator pnpm install ``` ### 3. Run the Example Use the `pnpm start` command to execute the workflow. **Run in one-shot mode** ```bash # Run in one-shot mode (default) pnpm start ``` **Run in interactive chat mode** ```bash # Run in interactive chat mode pnpm start -- --interactive ``` **Use pipeline input** ```bash # Use pipeline input echo "Research ArcBlock and compile a report about their products and architecture" | pnpm start ``` ## Run Options The script accepts several command-line parameters to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | Specify the AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (e.g., `ERROR`, `WARN`, `INFO`, `DEBUG`). | `INFO` | | `--input`, `-i ` | Specify input directly via the command line. | None | #### Examples **Run in interactive chat mode** ```bash # Run in chat mode pnpm start -- --interactive ``` **Set a different logging level** ```bash # Set logging level to DEBUG pnpm start -- --log-level DEBUG ``` ## Code Example The following TypeScript code demonstrates how to define and orchestrate multiple agents to perform in-depth research and compile a report. The `OrchestratorAgent` coordinates a `finder` and a `writer`, which are equipped with skills to browse the web (`puppeteer`) and interact with the local filesystem. **orchestrator.ts** ```typescript import { OrchestratorAgent } from "@aigne/agent-library/orchestrator/index.js"; import { AIAgent, AIGNE, MCPAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // 1. Initialize the chat model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, modelOptions: { parallelToolCalls: false, // Puppeteer can only run one task at a time }, }); // 2. Set up MCP agents for web scraping and filesystem access const puppeteer = await MCPAgent.from({ command: "npx", args: ["-y", "@modelcontextprotocol/server-puppeteer"], env: process.env as Record, }); const filesystem = await MCPAgent.from({ command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", import.meta.dir], }); // 3. Define the finder agent to research information const finder = AIAgent.from({ name: "finder", description: "Find the closest match to a user's request", instructions: `You are an agent that can find information on the web. You are tasked with finding the closest match to the user's request. You can use puppeteer to scrape the web for information. You can also use the filesystem to save the information you find. Rules: - do not use screenshot of puppeteer - use document.body.innerText to get the text content of a page - if you want a url to some page, you should get all link and it's title of current(home) page, then you can use the title to search the url of the page you want to visit. `, skills: [puppeteer, filesystem], }); // 4. Define the writer agent to save the report const writer = AIAgent.from({ name: "writer", description: "Write to the filesystem", instructions: `You are an agent that can write to the filesystem. You are tasked with taking the user's input, addressing it, and writing the result to disk in the appropriate location.`, skills: [filesystem], }); // 5. Create the orchestrator agent to manage the workflow const agent = OrchestratorAgent.from({ skills: [finder, writer], maxIterations: 3, tasksConcurrency: 1, // Puppeteer can only run one task at a time }); // 6. Initialize the AIGNE instance const aigne = new AIGNE({ model }); // 7. Invoke the workflow with a detailed prompt const result = await aigne.invoke( agent, `\ Conduct an in-depth research on ArcBlock using only the official website\ (avoid search engines or third-party sources) and compile a detailed report saved as arcblock.md. \ The report should include comprehensive insights into the company's products \ (with detailed research findings and links), technical architecture, and future plans.`, ); console.log(result); ``` When executed, this workflow produces a detailed markdown file. You can view an example of the generated output here: [arcblock-deep-research.md](https://github.com/AIGNE-io/aigne-framework/blob/main/examples/workflow-orchestrator/generated-report-arcblock.md). ## Summary This example illustrates the power of the AIGNE Framework for building complex, multi-agent workflows. By defining specialized agents and coordinating them with an orchestrator, you can automate sophisticated tasks that require multiple steps, such as research, content generation, and file manipulation. For more examples of advanced workflow patterns, explore the following sections: ::::card-group ::link-card{title="Sequential Workflows" description="Build pipelines where agents execute tasks in a strict, step-by-step order." icon="arrow-right" href="/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/"} ::link-card{title="Concurrent Workflows" description="Process multiple tasks simultaneously to improve performance and efficiency." icon="git-branch" href="/en/docs/aigne-framework/examples-workflow-concurrency-9dc03e/"} ::link-card{title="Agent Handoff" description="Create seamless transitions where one agent passes its output to another for further processing." icon="refresh" href="/en/docs/aigne-framework/examples-workflow-handoff-9dc03e/"} ::link-card{title="Group Chat" description="Enable multiple agents to collaborate and communicate in a shared environment." icon="users" href="/en/docs/aigne-framework/examples-workflow-group-chat-9dc03e/"} :::: --- ## Workflow Reflection URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-reflection-9dc03e/ Have you ever needed an AI to not just generate content, but also to critique and improve its own work? This guide demonstrates how to build a self-correcting workflow where one agent's output is reviewed and refined by another. By following these steps, you will learn how to implement this powerful iterative pattern using the AIGNE Framework. This example establishes a workflow with two distinct agents: a `Coder` and a `Reviewer`. The `Coder` agent is responsible for writing code to solve a user's request, while the `Reviewer` agent evaluates the code. If the `Reviewer` deems the code unsatisfactory, it provides constructive feedback and sends it back to the `Coder` for revision. This creates a loop of continuous improvement until the output meets the required standards. The following diagram illustrates this process: ```mermaid flowchart LR in(In) out(Out) coder(Coder) reviewer(Reviewer) in --Ideas--> coder ==Solution==> reviewer --Approved--> out reviewer ==Rejected==> coder classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px,color:#b35b39,font-weight:bolder; classDef processing fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px,color:#6B8F3C,font-weight:bolder; class in inputOutput class out inputOutput class coder processing class reviewer processing ``` ## Prerequisites To successfully run this example, your development environment must meet the following criteria: - Node.js: Version 20.0 or higher. - npm: Included with your Node.js installation. - OpenAI API Key: An API key is necessary for the example to communicate with OpenAI models. You can acquire one from the [OpenAI Platform](https://platform.openai.com/api-keys). ## Quick Start This example can be executed directly from the command line using `npx`, which eliminates the need for a local installation. ### Run the Example Open your terminal and use one of the following commands to run the workflow. To run in the default one-shot mode, which processes a single request and exits: **npx command** ```bash npx -y @aigne/example-workflow-reflection ``` To engage in an interactive session, use the `--interactive` flag: **npx command** ```bash npx -y @aigne/example-workflow-reflection --interactive ``` You can also pipe input directly into the command: **npx command** ```bash echo "Write a function to validate email addresses" | npx -y @aigne/example-workflow-reflection ``` ### Connect to an AI Model Upon first execution, the application will prompt you to configure a connection to an AI model, as no API keys have been set up yet. ```d2 direction: down In: { shape: oval } Out: { shape: oval } Coder: { shape: rectangle } Reviewer: { shape: rectangle } In -> Coder: "Ideas" Coder -> Reviewer: "Solution" Reviewer -> Out: "Approved" Reviewer -> Coder: "Rejected" ``` You are presented with the following options: #### 1. Connect via the Official AIGNE Hub (Recommended) This is the most straightforward method. New users are granted free credits to get started. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your default web browser will open a new tab, displaying an authorization page. 3. Follow the on-screen instructions to approve the connection request. #### 2. Connect via a Self-Hosted AIGNE Hub If you or your organization operates a private AIGNE Hub instance, follow these steps: 1. Select the second option: `Connect to a self-hosted AIGNE Hub`. 2. When prompted, enter the URL of your self-hosted AIGNE Hub instance. 3. Proceed with the on-screen instructions to finalize the connection. #### 3. Connect via a Third-Party Model Provider You can connect directly to a third-party LLM provider, such as OpenAI, by configuring the appropriate API key as an environment variable. For instance, to use an OpenAI model, set the `OPENAI_API_KEY` environment variable in your terminal: **Set OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` Replace `"YOUR_OPENAI_API_KEY"` with your actual key. Once the environment variable is set, run the `npx` command again. For details on configuring other providers like Google Gemini or DeepSeek, consult the `.env.local.example` file included in the source code. ## Installation from Source For developers who want to examine or customize the code, the repository can be cloned to run the example locally. ### 1. Clone the Repository **Clone the repository** ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` ### 2. Install Dependencies Navigate to the example's directory and use `pnpm` to install the necessary packages. **Install dependencies** ```bash cd aigne-framework/examples/workflow-reflection pnpm install ``` ### 3. Run the Example Execute the script using the `pnpm start` command. **Run in one-shot mode** ```bash pnpm start ``` To run in interactive chat mode, append the `--interactive` flag. The extra `--` is required to pass the flag to the script rather than to `pnpm` itself. **Run in interactive mode** ```bash pnpm start -- --interactive ``` To provide input via a pipeline: **Run with pipeline input** ```bash echo "Write a function to validate email addresses" | pnpm start ``` ## How It Works The workflow is orchestrated by two `AIAgent` instances, `coder` and `reviewer`, which communicate through a system of topics. This creates a message-driven state machine. 1. Initialization: The process begins when a message with the user's request is published to the `UserInputTopic`. 2. Coder Agent: The `coder` agent, which subscribes to `UserInputTopic`, receives the request. It generates the initial code and publishes its solution to a `review_request` topic. 3. Reviewer Agent: The `reviewer` agent subscribes to the `review_request` topic. It assesses the submitted code against criteria such as correctness, efficiency, and safety. 4. Decision and Routing: 5. - If the code is approved, the `reviewer` publishes the final, validated result to the `UserOutputTopic`, concluding the workflow. - If the code is rejected, the `reviewer` formulates feedback and publishes it to a `rewrite_request` topic. 6. Iteration: The `coder` agent also subscribes to the `rewrite_request` topic. When it receives feedback, it revises its code accordingly and resubmits it to the `review_request` topic, thereby repeating the cycle until approval is achieved. ### Code Implementation The following TypeScript code provides the complete implementation for defining and running the `coder` and `reviewer` agents. **reflection-workflow.ts** ```typescript import { AIAgent, AIGNE, UserInputTopic, UserOutputTopic } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; import { z } from "zod"; const { OPENAI_API_KEY } = process.env; // Initialize the model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // Define the Coder agent const coder = AIAgent.from({ subscribeTopic: [UserInputTopic, "rewrite_request"], publishTopic: "review_request", instructions: `\ You are a proficient coder. You write code to solve problems. Work with the reviewer to improve your code. Always put all finished code in a single Markdown code block. For example: \`\`\`python def hello_world(): print("Hello, World!") \`\`\` Respond using the following format: Thoughts: Code: Previous review result: {{feedback}} User's question: {{question}} `, outputSchema: z.object({ code: z.string().describe("Your code"), }), }); // Define the Reviewer agent const reviewer = AIAgent.from({ subscribeTopic: "review_request", publishTopic: (output) => output.approval ? UserOutputTopic : "rewrite_request", instructions: `\ You are a code reviewer. You focus on correctness, efficiency and safety of the code. The problem statement is: {{question}} The code is: \`\`\` {{code}} \`\`\` Previous feedback: {{feedback}} Please review the code. If previous feedback was provided, see if it was addressed. `, outputSchema: z.object({ approval: z.boolean().describe("APPROVE or REVISE"), feedback: z.object({ correctness: z.string().describe("Your comments on correctness"), efficiency: z.string().describe("Your comments on efficiency"), safety: z.string().describe("Your comments on safety"), suggested_changes: z .string() .describe("Your comments on suggested changes"), }), }), includeInputInOutput: true, }); // Initialize and run the AIGNE instance const aigne = new AIGNE({ model, agents: [coder, reviewer] }); aigne.publish( UserInputTopic, "Write a function to find the sum of all even numbers in a list.", ); const { message } = await aigne.subscribe(UserOutputTopic); console.log(message); ``` ### Example Output Once the workflow completes successfully, the final approved code and the reviewer's feedback are logged to the console as a JSON object. **Example Output** ```json { "code": "def sum_of_even_numbers(numbers):\n \"\"\"Function to calculate the sum of all even numbers in a list.\"\"\"\n return sum(number for number in numbers if number % 2 == 0)", "approval": true, "feedback": { "correctness": "The function correctly calculates the sum of all even numbers in the given list. It properly checks for evenness using the modulus operator and sums the valid numbers.", "efficiency": "The implementation is efficient as it uses a generator expression which computes the sum in a single pass over the list. This minimizes memory usage as compared to creating an intermediate list of even numbers.", "safety": "The function does not contain any safety issues. However, it assumes that all elements in the input list are integers. It would be prudent to handle cases where the input contains non-integer values (e.g., None, strings, etc.).", "suggested_changes": "Consider adding type annotations to the function for better clarity and potential type checking, e.g. `def sum_of_even_numbers(numbers: list[int]) -> int:`. Also, include input validation to ensure 'numbers' is a list of integers." } } ``` ## Debugging with AIGNE Observe To gain insight into the agent interactions, message flows, and overall execution, you can use the AIGNE observability tool. First, launch the observation server from a separate terminal window: **Start AIGNE Observe** ```bash aigne observe ``` The server runs locally and is accessible at `http://localhost:7893`. With the server running, any execution of your AIGNE application will capture detailed traces. Open the web interface in your browser to view a list of recent executions and inspect the specifics of each step in the workflow. ## Summary This guide has detailed the process of building a reflection workflow, where agents collaborate to iteratively improve an output. This pattern is a key technique for developing more dependable and sophisticated AI systems capable of self-correction. To explore other ways of coordinating agents, consider the following workflow patterns: ::::card-group ::link-card{title="Sequential Workflow" description="Build step-by-step processing pipelines with a guaranteed execution order." icon="arrow-right" href="/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/"} ::link-card{title="Workflow Orchestration" description="Coordinate multiple agents working together in sophisticated processing pipelines." icon="routes" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Workflow Router URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-router-9dc03e/ Have you ever needed to direct user queries to different specialized handlers based on their content? This guide provides a complete, step-by-step walkthrough for building a workflow that intelligently routes requests. You will learn how to create a "triage" agent that analyzes input and forwards it to the correct specialized agent, such as product support or feedback collection. The router workflow is a common and powerful pattern for creating sophisticated, multi-agent systems. It acts as a smart dispatcher, ensuring that user requests are handled by the agent best equipped for the task. This example demonstrates a triage agent that routes questions to one of three specialized agents: `productSupport`, `feedback`, or `other`. The diagram below illustrates the routing logic: ```d2 direction: down User: { shape: c4-person } Triage-Agent: { label: "Triage Agent" shape: rectangle } Specialized-Agents: { label: "Specialized Agents" shape: rectangle productSupport: { label: "Product Support Agent" } feedback: { label: "Feedback Agent" } other: { label: "Other Agent" } } User -> Triage-Agent: "User Query" Triage-Agent -> Specialized-Agents.productSupport: "Routes product questions" Triage-Agent -> Specialized-Agents.feedback: "Routes feedback" Triage-Agent -> Specialized-Agents.other: "Routes other questions" Specialized-Agents.productSupport -> User: "Response" Specialized-Agents.feedback -> User: "Response" Specialized-Agents.other -> User: "Response" ``` ## Prerequisites Before proceeding, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Comes bundled with Node.js. - OpenAI API Key: Required for the default model configuration. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). ## Quick Start You can run this example directly without a manual installation process using `npx`. ### Run the Example The example can be executed in several modes. 1. One-Shot Mode (Default) This command processes a single, hardcoded input and exits. ```bash npx -y @aigne/example-workflow-router ``` 2. Interactive Chat Mode Use the `--interactive` flag to start an interactive session where you can send multiple messages. ```bash npx -y @aigne/example-workflow-router --interactive ``` 3. Pipeline Mode Pipe input directly into the command. This is useful for integrating with other scripts. ```bash echo "How do I return a product?" | npx -y @aigne/example-workflow-router ``` ### Connect to an AI Model When you run the example for the first time, it will detect that no AI model has been configured and will prompt you for setup. ![Initial setup prompt for AI model connection](https://media.arcblock.io/lib/d3/d3dc01907bf69a64.w1600.webp) You have several options to connect to an AI model: #### 1. Connect to the AIGNE Hub (Recommended) This is the easiest way to get started. The official AIGNE Hub provides free credits for new users. 1. Select the first option: `Connect to the Arcblock official AIGNE Hub`. 2. Your web browser will open an authorization page. 3. Follow the on-screen instructions to approve the connection. ![Authorize AIGNE CLI to connect to AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) #### 2. Connect to a Self-Hosted AIGNE Hub If you are running your own instance of AIGNE Hub: 1. Select the second option: `Connect to your self-hosted AIGNE Hub`. 2. Enter the URL of your AIGNE Hub instance when prompted. ![Enter the URL of your self-hosted AIGNE Hub](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) #### 3. Connect via a Third-Party Model Provider You can also connect directly to a model provider like OpenAI by setting an environment variable. **Set OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` Replace `"YOUR_OPENAI_API_KEY"` with your actual key. After setting the environment variable, run the example command again. For other providers like Google Gemini or DeepSeek, refer to the `.env.local.example` file in the source code for the correct variable names. ## Full Example and Source Code The core logic involves defining several `AIAgent` instances: three specialized agents (`productSupport`, `feedback`, `other`) and one `triage` agent that acts as the router. The `triage` agent is configured with `toolChoice: "router"`, which instructs it to select one of its available `skills` (the other agents) to handle the input. Below is the complete TypeScript code for this example. **index.ts** ```typescript import { AIAgent, AIGNE } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); const productSupport = AIAgent.from({ name: "product_support", description: "Agent to assist with any product-related questions.", instructions: `You are an agent capable of handling any product-related questions. Your goal is to provide accurate and helpful information about the product. Be polite, professional, and ensure the user feels supported.`, outputKey: "product_support", }); const feedback = AIAgent.from({ name: "feedback", description: "Agent to assist with any feedback-related questions.", instructions: `You are an agent capable of handling any feedback-related questions. Your goal is to listen to the user's feedback, acknowledge their input, and provide appropriate responses. Be empathetic, understanding, and ensure the user feels heard.`, outputKey: "feedback", }); const other = AIAgent.from({ name: "other", description: "Agent to assist with any general questions.", instructions: `You are an agent capable of handling any general questions. Your goal is to provide accurate and helpful information on a wide range of topics. Be friendly, knowledgeable, and ensure the user feels satisfied with the information provided.`, outputKey: "other", }); const triage = AIAgent.from({ name: "triage", instructions: `You are an agent capable of routing questions to the appropriate agent. Your goal is to understand the user's query and direct them to the agent best suited to assist them. Be efficient, clear, and ensure the user is connected to the right resource quickly.`, skills: [productSupport, feedback, other], toolChoice: "router", // Set toolChoice to "router" to enable router mode }); const aigne = new AIGNE({ model }); // Example 1: Route to Product Support const result1 = await aigne.invoke(triage, "How to use this product?"); console.log(result1); // Example 2: Route to Feedback const result2 = await aigne.invoke(triage, "I have feedback about the app."); console.log(result2); // Example 3: Route to Other const result3 = await aigne.invoke(triage, "What is the weather today?"); console.log(result3); ``` ### Execution and Output When the script runs, the `aigne.invoke` method sends the user's query to the `triage` agent. The agent then routes the query to the most appropriate specialized agent, and the final output is from that selected agent. Output for "How to use this product?" ```json { "product_support": "I’d be happy to help you with that! However, I need to know which specific product you’re referring to. Could you please provide me with the name or type of product you have in mind?" } ``` Output for "I have feedback about the app." ```json { "feedback": "Thank you for sharing your feedback! I'm here to listen. Please go ahead and let me know what you’d like to share about the app." } ``` Output for "What is the weather today?" ```json { "other": "I can't provide real-time weather updates. However, you can check a reliable weather website or a weather app on your phone for the current conditions in your area. If you tell me your location, I can suggest a few sources where you can find accurate weather information!" } ``` ## Command-Line Options The example script accepts several command-line arguments to customize its behavior. | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode instead of one-shot. | Disabled | | `--model ` | Specify the AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging verbosity (e.g., `ERROR`, `WARN`, `INFO`, `DEBUG`). | `INFO` | | `--input`, `-i ` | Provide input directly as an argument. | None | #### Examples **Run in interactive mode** ```bash npx -y @aigne/example-workflow-router --interactive ``` **Set a specific model and temperature** ```bash npx -y @aigne/example-workflow-router --model openai:gpt-4o-mini --temperature 0.5 -i "Tell me about your product." ``` **Set logging level to debug** ```bash npx -y @aigne/example-workflow-router --log-level DEBUG ``` ## Debugging To inspect the execution flow and understand the agent's behavior, you can use the AIGNE observability tool. First, start the observation server in a separate terminal window: ```bash aigne observe ``` ![AIGNE observe command running in the terminal](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) The server will start, and you can access the web interface at `http://localhost:7893`. After running the example, the execution traces will appear in the dashboard, allowing you to see how the `triage` agent made its routing decision and what data was passed between agents. ![AIGNE observability interface showing a list of traces](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This example has demonstrated how to build a router workflow using the AIGNE Framework. By defining a `triage` agent with specialized agents as its skills and setting `toolChoice: "router"`, you can create a powerful system that intelligently delegates tasks. For more complex patterns, explore the following examples: ::::card-group ::link-card{title="Workflow Handoff" description="Create seamless transitions between specialized agents to solve complex problems." icon="refresh" href="/en/docs/aigne-framework/examples-workflow-handoff-9dc03e/"} ::link-card{title="Workflow Orchestration" description="Coordinate multiple agents working together in sophisticated processing pipelines." icon="routes" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Workflow Sequential URL: https://www.arcblock.io/en/docs/aigne-framework/examples-workflow-sequential-9dc03e/ This guide demonstrates how to construct and execute a sequential workflow using the AIGNE Framework. You will learn how to chain multiple agents together, where the output of one agent becomes the input for the next, creating a step-by-step processing pipeline. This pattern is ideal for tasks that require a series of distinct, ordered operations. ## Overview A sequential workflow processes tasks in a predefined order. Each agent in the sequence performs a specific function and passes its result to the subsequent agent. This ensures a predictable and controlled execution flow, similar to an assembly line. This example builds a simple marketing content generation pipeline composed of three agents: ::::steps :::step{title="Concept Extractor"} Analyzes a product description to identify key features, target audience, and unique selling points. ::: :::step{title="Writer"} Uses the extracted concepts to compose a compelling marketing copy. ::: :::step{title="Format Proof"} Refines the draft copy by correcting grammar, improving clarity, and ensuring a polished final output. ::: :::: The data flows through the agents in a strict sequence as illustrated below. ```mermaid flowchart LR in(In) out(Out) conceptExtractor(Concept Extractor) writer(Writer) formatProof(Format Proof) in --> conceptExtractor --> writer --> formatProof --> out classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px,color:#b35b39,font-weight:bolder; classDef processing fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px,color:#6B8F3C,font-weight:bolder; class in inputOutput class out inputOutput class conceptExtractor processing class writer processing class formatProof processing ``` ## Prerequisites Before running the example, ensure your development environment meets the following requirements: - Node.js: Version 20.0 or higher. - npm: Included with Node.js. - OpenAI API Key: Required for the model interactions in this example. You can obtain one from the [OpenAI Platform](https://platform.openai.com/api-keys). ## Quick Start You can run this example directly without a local installation using `npx`. ### Run the Example Execute the following commands in your terminal. To run in the default one-shot mode: ```bash npx -y @aigne/example-workflow-sequential ``` To run in an interactive chat mode: ```bash npx -y @aigne/example-workflow-sequential --interactive ``` You can also pipe input directly into the command: ```bash echo "Create marketing content for our new AI-powered fitness app" | npx -y @aigne/example-workflow-sequential ``` ### Connect to an AI Model The first time you run the example, the application will detect that no AI model has been configured and will prompt you to connect to one. ![Initial prompt to connect an AI model](https://media.arcblock.io/lib/d5/d559dd2a1f34acaa.w1600.webp) You have several options to proceed: 1. Connect via the Official AIGNE Hub (Recommended) This is the most straightforward method to get started. New users receive a complimentary token balance for trial purposes. - Select the first option in the prompt: `Connect to the Arcblock official AIGNE Hub`. - Your default web browser will open a new tab to the AIGNE Hub authorization page. - Follow the on-screen instructions to approve the connection. ![Authorize connection to AIGNE Hub](https://media.arcblock.io/lib/71/71683af3a27ab961.w1600.webp) 2. Connect via a Self-Hosted AIGNE Hub If you operate your own instance of AIGNE Hub, you can connect to it directly. - Select the second option: `Connect to my own AIGNE Hub`. - Enter the URL of your self-hosted AIGNE Hub instance when prompted in the terminal. ![Enter self-hosted AIGNE Hub URL](https://media.arcblock.io/lib/8c/8ccdbc027ddcbb8f.w1600.webp) 3. Connect via a Third-Party Model Provider You can also connect directly to a supported third-party model provider, such as OpenAI. This requires setting the appropriate API key as an environment variable. For OpenAI, export the `OPENAI_API_KEY` variable: **Set OpenAI API Key** ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` Replace `"YOUR_OPENAI_API_KEY"` with your actual key. After setting the environment variable, execute the run command again. For details on configuring other providers, refer to the `.env.local.example` file in the project repository. ## Installation (Optional) If you prefer to run the example from a local clone of the repository, follow these steps. 1. Clone the Repository ```bash git clone https://github.com/AIGNE-io/aigne-framework ``` 2. Install Dependencies Navigate to the example's directory and install the required packages using `pnpm`. ```bash cd aigne-framework/examples/workflow-sequential pnpm install ``` 3. Run the Example Use the `pnpm start` command to execute the workflow. Run in one-shot mode: ```bash pnpm start ``` Run in interactive chat mode (note the `--` before the argument): ```bash pnpm start -- --interactive ``` Use pipeline input: ```bash echo "Create marketing content for our new AI-powered fitness app" | pnpm start ``` ### Command-Line Options The example supports several command-line arguments for customization: | Parameter | Description | Default | |---|---|---| | `--interactive` | Run in interactive chat mode. | Disabled | | `--model ` | Specify the AI model to use (e.g., `openai` or `openai:gpt-4o-mini`). | `openai` | | `--temperature ` | Set the temperature for model generation. | Provider default | | `--top-p ` | Set the top-p sampling value. | Provider default | | `--presence-penalty ` | Set the presence penalty value. | Provider default | | `--frequency-penalty ` | Set the frequency penalty value. | Provider default | | `--log-level ` | Set the logging level (`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`). | `INFO` | | `--input`, `-i ` | Provide input directly as an argument. | `None` | ## Code Example The core logic of the sequential workflow is defined in a single TypeScript file. It initializes three distinct `AIAgent` instances and orchestrates them within a `TeamAgent` configured for sequential execution. **sequential-workflow.ts** ```typescript import { AIAgent, AIGNE, ProcessMode, TeamAgent } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js"; const { OPENAI_API_KEY } = process.env; // 1. Initialize the model const model = new OpenAIChatModel({ apiKey: OPENAI_API_KEY, }); // 2. Define the first agent in the sequence const conceptExtractor = AIAgent.from({ instructions: `\ You are a marketing analyst. Give a product description, identity: - Key features - Target audience - Unique selling points Product description: {{product}}`, outputKey: "concept", }); // 3. Define the second agent const writer = AIAgent.from({ instructions: `\ You are a marketing copywriter. Given a block of text describing features, audience, and USPs, compose a compelling marketing copy (like a newsletter section) that highlights these points. Output should be short (around 150 words), output just the copy as a single text block. Product description: {{product}} Below is the info about the product: {{concept}}`, outputKey: "draft", }); // 4. Define the third agent const formatProof = AIAgent.from({ instructions: `\ You are an editor. Given the draft copy, correct grammar, improve clarity, ensure consistent tone, give format and make it polished. Output the final improved copy as a single text block. Product description: {{product}} Below is the info about the product: {{concept}} Draft copy: {{draft}}`, outputKey: "content", }); // 5. Initialize the AIGNE instance const aigne = new AIGNE({ model }); // 6. Create a TeamAgent to manage the sequential workflow const teamAgent = TeamAgent.from({ skills: [conceptExtractor, writer, formatProof], mode: ProcessMode.sequential, // This ensures agents run one after another }); // 7. Invoke the workflow with initial input const result = await aigne.invoke(teamAgent, { product: "AIGNE is a No-code Generative AI Apps Engine", }); console.log(result); /* // Expected Output Structure: { concept: "...", // Output from conceptExtractor draft: "...", // Output from writer content: "..." // Output from formatProof } */ ``` This script demonstrates the following key steps: 1. An `OpenAIChatModel` instance is created to handle communication with the LLM. 2. Three `AIAgent` instances (`conceptExtractor`, `writer`, `formatProof`) are defined with specific instructions. Each agent's `outputKey` determines the key under which its result is stored. 3. The `writer` agent uses the output of the `conceptExtractor` via the `{{concept}}` placeholder. Similarly, `formatProof` uses `{{concept}}` and `{{draft}}`. 4. A `TeamAgent` is configured with the three agents in its `skills` array. The `mode` is set to `ProcessMode.sequential`, which instructs the team to execute the agents in the order they are provided. 5. Finally, `aigne.invoke()` starts the workflow, passing the initial product description. The final result is an object containing the outputs from all agents in the sequence. ## Debugging To monitor and debug the execution of your agents, you can use the `aigne observe` command. This tool provides a web-based interface to inspect traces, review inputs and outputs, and analyze the performance of your workflow. First, start the observation server in your terminal: ```bash aigne observe ``` The server will start, and you can access the UI at `http://localhost:7893`. ![AIGNE Observe server starting in the terminal](https://media.arcblock.io/lib/cc/cc02f9ff8f8e9cb3.w1600.webp) After running your workflow, the execution trace will appear in the observability interface, allowing you to examine each step of the sequence in detail. ![List of recent agent traces in the AIGNE Observability UI](https://media.arcblock.io/lib/30/305233c275170db3.w1600.webp) ## Summary This guide covered the setup and execution of a sequential workflow. By defining a series of agents and orchestrating them with a `TeamAgent` in sequential mode, you can build powerful, multi-step processing pipelines for complex tasks. For more advanced workflow patterns, explore the following examples: ::::card-group ::link-card{title="Workflow: Parallel Execution" description="Learn how to run multiple agents simultaneously to improve performance." icon="git-branch" href="/en/docs/aigne-framework/examples-workflow-concurrency-9dc03e/"} ::link-card{title="Workflow: Orchestration" description="Coordinate multiple agents in more complex, non-linear pipelines." icon="routes" href="/en/docs/aigne-framework/examples-workflow-orchestration-9dc03e/"} :::: --- ## Models URL: https://www.arcblock.io/en/docs/aigne-framework/models-9dc03e/ The AIGNE Framework is designed to be model-agnostic, allowing you to connect to a wide range of third-party AI model providers. This flexibility is achieved through a system of model adapters, where each adapter provides a standardized interface for a specific service, such as OpenAI, Anthropic, or Google Gemini. This section provides detailed guides for installing, configuring, and using each officially supported model provider. Whether you need powerful language models, specialized image and video generation, or the privacy of a locally hosted model, you can find the right integration here. ## Supported Model Providers Below is a curated list of supported providers. Each card links to a dedicated guide with installation instructions, configuration details, and practical code examples. ### Foundational Models These are direct integrations with major AI model providers for chat completions and other language-based tasks. ::::card-group ::link-card{title="OpenAI" description="Integrate with OpenAI's suite of models, including the powerful GPT-4o, for chat completions and function calling." icon="brain" href="/en/docs/aigne-framework/models-openai-9dc03e/"} ::link-card{title="Anthropic" description="Leverage Anthropic's Claude models, known for their strong performance in complex reasoning and conversation." icon="bot" href="/en/docs/aigne-framework/models-anthropic-9dc03e/"} ::link-card{title="Google Gemini" description="Connect to Google's Gemini family of multimodal models for advanced text and image understanding." icon="sparkles" href="/en/docs/aigne-framework/models-gemini-9dc03e/"} ::link-card{title="AWS Bedrock" description="Access a variety of foundation models from providers like Anthropic, Cohere, and Amazon through AWS Bedrock." icon="cloud" href="/en/docs/aigne-framework/models-bedrock-9dc03e/"} ::link-card{title="DeepSeek" description="Utilize DeepSeek's powerful and efficient language models for a range of natural language processing tasks." icon="brain" href="/en/docs/aigne-framework/models-deepseek-9dc03e/"} ::link-card{title="Doubao" description="Integrate with Doubao's language models for building conversational AI and other text-based applications." icon="bot" href="/en/docs/aigne-framework/models-doubao-9dc03e/"} ::link-card{title="xAI" description="Connect to xAI's Grok models, designed for real-time information processing and a unique conversational style." icon="sparkles" href="/en/docs/aigne-framework/models-xai-9dc03e/"} :::: ### Image Generation Models Specialized integrations for creating visual content from text prompts. ::::card-group ::link-card{title="Ideogram" description="Generate high-quality images with reliable text rendering using Ideogram's advanced synthesis models." icon="image" href="/en/docs/aigne-framework/models-ideogram-9dc03e/"} ::link-card{title="OpenAI" description="Use DALL-E 3 and other models for creative and diverse image generation capabilities." icon="brain" href="/en/docs/aigne-framework/models-openai-9dc03e/"} ::link-card{title="Google Gemini" description="Leverage Gemini and Imagen models for versatile image generation and editing alongside language features." icon="sparkles" href="/en/docs/aigne-framework/models-gemini-9dc03e/"} :::: ### Video Generation Models Integrations for generating video content from text or image inputs. ::::card-group ::link-card{title="OpenAI" description="Generate high-quality video content from text or image prompts using OpenAI's Sora models." icon="brain" href="/en/docs/aigne-framework/models-openai-9dc03e/"} ::link-card{title="Google Gemini" description="Create video from text or images using Google's Veo models for dynamic content generation." icon="sparkles" href="/en/docs/aigne-framework/models-gemini-9dc03e/"} ::link-card{title="AIGNE Hub" description="Access video generation models like OpenAI Sora and Google Veo through a unified API endpoint." icon="routes" href="/en/docs/aigne-framework/models-aigne-hub-9dc03e/"} :::: ### Local and Aggregator Services Connect to local instances or services that provide access to multiple models through a single API. ::::card-group ::link-card{title="Ollama" description="Run open-source models like Llama 3 locally on your own hardware for maximum privacy and offline access." icon="server" href="/en/docs/aigne-framework/models-ollama-9dc03e/"} ::link-card{title="LMStudio" description="Connect to models running locally via the LMStudio application, providing a simple way to experiment with open-source AI." icon="monitor" href="/en/docs/aigne-framework/models-lmstudio-9dc03e/"} ::link-card{title="OpenRouter" description="Access a wide variety of models from different providers through a single, unified API with fallback options." icon="routes" href="/en/docs/aigne-framework/models-open-router-9dc03e/"} ::link-card{title="Poe" description="Integrate with various models available through the Poe platform, offering a diverse set of AI capabilities." icon="message-square" href="/en/docs/aigne-framework/models-poe-9dc03e/"} ::link-card{title="AIGNE Hub" description="Use the AIGNE Hub as a unified proxy to seamlessly switch between multiple LLM providers without changing client-side code." icon="routes" href="/en/docs/aigne-framework/models-aigne-hub-9dc03e/"} :::: ## Summary The AIGNE Framework's modular design makes it easy to integrate with the best AI model for your specific needs. Each provider has a dedicated package that handles the complexities of the underlying API, presenting you with a consistent and straightforward interface. To get started, choose a provider from the list above and follow the linked guide for detailed instructions. For a high-level overview of how model adapters work within the framework, see the [Overview](/en/docs/aigne-framework/models-overview-9dc03e/) page. --- ## AIGNE Hub URL: https://www.arcblock.io/en/docs/aigne-framework/models-aigne-hub-9dc03e/ The AIGNE Hub provides a unified proxy layer for accessing a variety of Large Language Models (LLMs), image, and video generation services from multiple providers. By using the `@aigne/aigne-hub` package, you can seamlessly switch between different AI models without altering your client-side application logic, directing all requests through a single, consistent API endpoint. This guide covers the installation, configuration, and usage of the `AIGNEHubChatModel`, `AIGNEHubImageModel`, and `AIGNEHubVideoModel` classes to connect your application to the AIGNE Hub. ## Overview AIGNE Hub acts as a gateway, aggregating major AI providers such as OpenAI, Anthropic, Google, and others. This architecture simplifies integration by abstracting the specific requirements of each provider's API. You interact with any supported model by simply passing its unique identifier, which includes the provider prefix (e.g., `openai/gpt-4o-mini` or `anthropic/claude-3-sonnet`). ### Key Features - Unified Access: A single endpoint for all LLM, image, and video generation requests. - Multi-Provider Support: Access models from OpenAI, Anthropic, AWS Bedrock, Google, DeepSeek, Ollama, xAI, and OpenRouter. - Secure Authentication: Manage access through a single API key (`apiKey`). - Chat, Image, and Video Models: Supports chat completions, image generation, and video creation. - Streaming: Real-time, token-level streaming for chat responses. - Seamless Integration: Designed to work with the broader AIGNE Framework. ### Supported Providers AIGNE Hub supports a wide range of AI providers through its unified API. | Provider | Identifier | |---|---| | OpenAI | `openai` | | Anthropic | `anthropic` | | AWS Bedrock | `bedrock` | | DeepSeek | `deepseek` | | Google | `google` | | Ollama | `ollama` | | OpenRouter | `openRouter` | | xAI | `xai` | ## Installation To get started, install the `@aigne/aigne-hub` and `@aigne/core` packages in your project. **npm install** ```bash npm install @aigne/aigne-hub @aigne/core ``` **yarn add** ```bash yarn add @aigne/aigne-hub @aigne/core ``` **pnpm add** ```bash pnpm add @aigne/aigne-hub @aigne/core ``` ## Configuration The chat, image, and video models require configuration to connect to your AIGNE Hub instance. The primary options include the Hub's URL, an access key, and the desired model identifier. ### Model Configuration The configuration options are consistent across `AIGNEHubChatModel`, `AIGNEHubImageModel`, and `AIGNEHubVideoModel`. - **baseUrl** `string` *(required)* — The base URL of your AIGNE Hub instance (e.g., https://your-aigne-hub-instance/ai-kit). - **apiKey** `string` *(required)* — Your API access key for authenticating with the AIGNE Hub. - **model** `string` *(required)* — The model identifier, prefixed with the provider (e.g., openai/gpt-4o-mini). - **modelOptions** `object` — Optional model-specific parameters to pass through to the provider's API. ## Usage ### Chat Completions To perform a chat completion, instantiate `AIGNEHubChatModel` with your configuration and call the `invoke` method. **Basic Chat Completion** ```typescript import { AIGNEHubChatModel } from "@aigne/aigne-hub"; const model = new AIGNEHubChatModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "openai/gpt-4o-mini", }); const result = await model.invoke({ messages: [{ role: "user", content: "Hello, world!" }], }); console.log(result); ``` Example Response ```json { "text": "Hello! How can I help you today?", "model": "openai/gpt-4o-mini", "usage": { "inputTokens": 8, "outputTokens": 9 } } ``` Example Models: - `openai/gpt-4o-mini` - `anthropic/claude-3-sonnet` - `google/gemini-pro` - `xai/grok-1` - `openRouter/mistralai/mistral-7b-instruct` - `ollama/llama3` ### Streaming Chat Responses For real-time responses, set the `streaming` option to `true` in the `invoke` call. This returns an async iterator that yields response chunks as they become available. **Streaming Example** ```typescript import { AIGNEHubChatModel } from "@aigne/aigne-hub"; import { isAgentResponseDelta } from "@aigne/core"; const model = new AIGNEHubChatModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "openai/gpt-4o-mini", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Hello, who are you?" }], }, { streaming: true }, ); let fullText = ""; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); } } } console.log("\n--- Response Complete ---"); console.log(fullText); ``` ### Image Generation AIGNE Hub supports image generation from multiple providers. Instantiate `AIGNEHubImageModel` and provide a prompt and model-specific parameters. #### OpenAI DALL-E **Generate with DALL-E 3** ```typescript import { AIGNEHubImageModel } from "@aigne/aigne-hub"; const model = new AIGNEHubImageModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "openai/dall-e-3", }); const result = await model.invoke({ prompt: "A futuristic cityscape with flying cars and neon lights", n: 1, size: "1024x1024", quality: "standard", style: "natural", }); console.log(result.images[0].url); ``` - Reference: [OpenAI Images API Documentation](https://platform.openai.com/docs/guides/images) #### Google Gemini Imagen **Generate with Imagen** ```typescript import { AIGNEHubImageModel } from "@aigne/aigne-hub"; const model = new AIGNEHubImageModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "google/imagen-4.0-generate-001", }); const result = await model.invoke({ prompt: "A serene mountain landscape at sunset", n: 1, aspectRatio: "1:1", }); console.log(result.images[0].base64); // Note: Gemini models return base64 data ``` - Reference: [Google AI Generative Models API](https://googleapis.github.io/js-genai/release_docs/classes/models.Models.html) #### Ideogram **Generate with Ideogram** ```typescript import { AIGNEHubImageModel } from "@aigne/aigne-hub"; const model = new AIGNEHubImageModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "ideogram/ideogram-v3", }); const result = await model.invoke({ prompt: "A cyberpunk character with glowing blue eyes, cinematic style", aspectRatio: "1:1", styleType: "cinematic", }); console.log(result.images[0].url); ``` - Reference: [Ideogram API Documentation](https://developer.ideogram.ai/api-reference/api-reference/generate-v3) ### Video Generation AIGNE Hub extends its unified API to AI-powered video generation from leading providers. To create a video, instantiate `AIGNEHubVideoModel` with the appropriate configuration. #### OpenAI Sora **Generate with Sora** ```typescript import { AIGNEHubVideoModel } from "@aigne/aigne-hub"; const model = new AIGNEHubVideoModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "openai/sora-2", }); const result = await model.invoke({ prompt: "A serene beach scene with gentle waves at sunset", size: "1280x720", seconds: "8", outputFileType: "url", }); console.log(result); ``` Example Response ```json { "videos": [{ "url": "https://...", "type": "url" }], "usage": { "inputTokens": 0, "outputTokens": 0, "aigneHubCredits": 200 }, "model": "openai/sora-2", "seconds": 8 } ``` - Reference: [OpenAI Video API Documentation](https://platform.openai.com/docs/api-reference/videos) #### Google Gemini Veo **Generate with Veo** ```typescript import { AIGNEHubVideoModel } from "@aigne/aigne-hub"; const model = new AIGNEHubVideoModel({ baseUrl: "https://your-aigne-hub-instance/ai-kit", apiKey: "your-access-key-secret", model: "google/veo-3.1-generate-preview", }); const result = await model.invoke({ prompt: "A majestic eagle soaring through mountain valleys", aspectRatio: "16:9", size: "1080p", seconds: "6", outputFileType: "url", }); console.log(result); ``` Example Response ```json { "videos": [{ "url": "https://...", "type": "url" }], "usage": { "inputTokens": 0, "outputTokens": 0, "aigneHubCredits": 150 }, "model": "google/veo-3.1-generate-preview", "seconds": 6 } ``` - Reference: [Google Gemini Video API Documentation](https://ai.google.dev/api/generate-videos) ## Summary The `@aigne/aigne-hub` package simplifies multi-provider LLM integration by offering a unified client for the AIGNE Hub service. By abstracting provider-specific logic for chat, image, and video models, it enables developers to build more flexible and maintainable AI-powered applications. For more detailed information on specific models and their capabilities, please refer to the documentation provided by each respective AI provider. To explore other model integrations, see the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/). --- ## Anthropic URL: https://www.arcblock.io/en/docs/aigne-framework/models-anthropic-9dc03e/ This guide provides instructions for configuring and using Anthropic's Claude models within the AIGNE Framework via the `@aigne/anthropic` package. It covers API key setup, model instantiation, and invoking the model for both standard and streaming responses. For a general overview of how models work within the AIGNE framework, please refer to the [Models core concepts](/en/docs/aigne-framework/developer-guide-core-concepts-models-9dc03e/) documentation. ## Introduction The `@aigne/anthropic` package provides a direct and seamless integration between the AIGNE Framework and Anthropic's powerful Claude language models. This allows developers to leverage the advanced capabilities of models like Claude 3.5 Sonnet and Claude 3 Opus through the standardized `ChatModel` interface, ensuring consistency across your agentic applications. Key features of this integration include: - Direct API Integration: Utilizes the official Anthropic SDK for reliable communication. - Chat Completions: Full support for Anthropic's chat completions API. - Tool Calling: Natively supports Claude's tool-calling functionality. - Streaming Responses: Enables real-time, responsive applications by handling streaming outputs. - Type-Safe: Comes with comprehensive TypeScript typings for robust development. ## Installation To get started, install the `@aigne/anthropic` package along with the core AIGNE package using your preferred package manager. ```bash npm install @aigne/anthropic @aigne/core ``` ```bash yarn add @aigne/anthropic @aigne/core ``` ```bash pnpm add @aigne/anthropic @aigne/core ``` ## Configuration The `AnthropicChatModel` class is the primary entry point for interacting with Claude models. To instantiate it, you need to provide your Anthropic API key and optionally specify a model and other configurations. ### API Key Your Anthropic API key can be configured in one of three ways, in order of precedence: ::::steps :::step{title="Directly in the constructor"} Pass the key via the `apiKey` property. ::: :::step{title="`ANTHROPIC_API_KEY`"} environment variable: The model will automatically detect and use this variable. ::: :::step{title="`CLAUDE_API_KEY`"} environment variable: An alternative environment variable that is also supported. ::: :::: **Instantiating the Model** ```typescript import { AnthropicChatModel } from "@aigne/anthropic"; const model = new AnthropicChatModel({ // Option 1: Provide the API key directly apiKey: "your-anthropic-api-key", // The model will automatically use ANTHROPIC_API_KEY or CLAUDE_API_KEY // if they are set in your environment and apiKey is not provided. }); ``` ### Model Selection You can specify which Claude model to use with the `model` property. If not specified, it defaults to `claude-3-7-sonnet-latest`. Other common model parameters like `temperature` can be set within the `modelOptions` object. A list of commonly used models includes: - `claude-3-5-sonnet-20240620` - `claude-3-opus-20240229` - `claude-3-sonnet-20240229` - `claude-3-haiku-20240307` **Model Configuration** ```typescript import { AnthropicChatModel } from "@aigne/anthropic"; const model = new AnthropicChatModel({ apiKey: "your-anthropic-api-key", // Specify the model version model: "claude-3-haiku-20240307", // Configure other model behaviors modelOptions: { temperature: 0.7, // Controls randomness (0.0 to 1.0) }, }); ``` ## Basic Usage To generate a response, use the `invoke` method. Pass a list of messages to the model to start a conversation. The method returns a promise that resolves with the model's output, including the text response and token usage statistics. **Basic Chat Completion** ```typescript import { AnthropicChatModel } from "@aigne/anthropic"; const model = new AnthropicChatModel({ apiKey: "your-anthropic-api-key", model: "claude-3-haiku-20240307", }); const result = await model.invoke({ messages: [{ role: "user", content: "Tell me about yourself" }], }); console.log(result); ``` The `result` object contains the generated text and other metadata from the API. Example Response ```json { "text": "I am Claude, a large language model trained by Anthropic.", "model": "claude-3-haiku-20240307", "usage": { "inputTokens": 8, "outputTokens": 12 } } ``` ## Streaming Responses For applications requiring real-time interaction, you can enable streaming by setting the `streaming` option to `true` in the `invoke` method. This returns an async iterator that yields response chunks as they become available. The `isAgentResponseDelta` utility can be used to check if a chunk contains new data. **Streaming Example** ```typescript import { AnthropicChatModel } from "@aigne/anthropic"; import { isAgentResponseDelta } from "@aigne/core"; const model = new AnthropicChatModel({ apiKey: "your-anthropic-api-key", model: "claude-3-haiku-20240307", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Tell me a short story about a robot." }], }, { streaming: true }, ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { process.stdout.write(text); // Print text to the console as it arrives fullText += text; } if (chunk.delta.json) { Object.assign(json, chunk.delta.json); } } } console.log("\n\n--- Final Response ---"); console.log(fullText); console.log(json); ``` This code processes the stream, printing text chunks to the console immediately and accumulating the full response and metadata. ## Summary You now have the necessary information to install, configure, and use Anthropic's Claude models within your AIGNE applications. You can perform basic invocations for simple tasks or use streaming for more interactive experiences. To learn more about orchestrating multiple models and agents, see the [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/) documentation. For details on other available models, visit the main [Models](/en/docs/aigne-framework/models-9dc03e/) section. --- ## AWS Bedrock URL: https://www.arcblock.io/en/docs/aigne-framework/models-bedrock-9dc03e/ The `@aigne/bedrock` package provides a direct and robust integration between the AIGNE Framework and Amazon Web Services (AWS) Bedrock. This allows developers to leverage the diverse range of foundation models available through AWS Bedrock within their AIGNE applications, benefiting from AWS's scalable and secure infrastructure while maintaining a consistent interface. This guide provides a systematic overview of the installation, configuration, and usage of the `BedrockChatModel`. For details on other models, please refer to the main [Models overview](/en/docs/aigne-framework/models-overview-9dc03e/). ## Installation To begin, install the necessary packages using your preferred package manager. The `@aigne/core` package is a required peer dependency. **Terminal** ```bash # Using npm npm install @aigne/bedrock @aigne/core # Using yarn yarn add @aigne/bedrock @aigne/core # Using pnpm pnpm add @aigne/bedrock @aigne/core ``` ## Configuration Proper configuration involves setting up AWS credentials and instantiating the `BedrockChatModel` with the desired parameters. ### AWS Credentials The AWS SDK requires credentials to authenticate requests. You can provide them in one of two ways: 1. Environment Variables (Recommended): Set the following environment variables in your development or deployment environment. The SDK will automatically detect and use them. 2. - `AWS_ACCESS_KEY_ID`: Your AWS access key ID. - `AWS_SECRET_ACCESS_KEY`: Your AWS secret access key. - `AWS_REGION`: The AWS region where your Bedrock service is enabled (e.g., `us-east-1`). 3. Direct Instantiation: Pass the credentials directly to the `BedrockChatModel` constructor. This method is suitable for specific use cases but is generally less secure than using environment variables. ### BedrockChatModel Options The `BedrockChatModel` is the primary class for interacting with AWS Bedrock. Its constructor accepts an options object to configure its behavior. - **accessKeyId** `string` — Your AWS access key ID. If not provided, the SDK will attempt to read it from the AWS_ACCESS_KEY_ID environment variable. - **secretAccessKey** `string` — Your AWS secret access key. If not provided, the SDK will attempt to read it from the AWS_SECRET_ACCESS_KEY environment variable. - **region** `string` — The AWS region for the Bedrock service. If not provided, the SDK will attempt to read it from the AWS_REGION environment variable. - **model** `string` (default: `us.amazon.nova-lite-v1:0`) — The ID of the foundation model to use (e.g., anthropic.claude-3-sonnet-20240229-v1:0, meta.llama3-8b-instruct-v1:0). - **modelOptions** `object` — Additional options to control model inference behavior. - **temperature** `number` — Controls randomness in the generation. Higher values mean more creative responses. - **topP** `number` — Controls nucleus sampling. The model considers only the tokens with the top P probability mass. - **clientOptions** `object` — Advanced configuration options passed directly to the underlying BedrockRuntimeClient from the AWS SDK. ## Usage Examples The following examples demonstrate how to use the `BedrockChatModel` for both standard and streaming invocations. ### Basic Usage This example shows how to instantiate the model and invoke it to get a single, complete response. **Basic Invocation** ```typescript import { BedrockChatModel } from "@aigne/bedrock"; // Instantiate the model with credentials and model ID const model = new BedrockChatModel({ accessKeyId: "YOUR_ACCESS_KEY_ID", // Or use environment variables secretAccessKey: "YOUR_SECRET_ACCESS_KEY", // Or use environment variables region: "us-east-1", // Specify your AWS region model: "anthropic.claude-3-haiku-20240307-v1:0", modelOptions: { temperature: 0.7, }, }); // Define the input messages const result = await model.invoke({ messages: [{ role: "user", content: "Hello, what is AWS Bedrock?" }], }); console.log(result.text); ``` The output will be a string containing the model's response. The `result` object also contains usage metrics. ### Streaming Responses For applications requiring real-time feedback, you can stream the response as it is generated. This is useful for chatbots and other interactive experiences. **Streaming Invocation** ```typescript import { BedrockChatModel } from "@aigne/bedrock"; import { isAgentResponseDelta } from "@aigne/core"; const model = new BedrockChatModel({ accessKeyId: "YOUR_ACCESS_KEY_ID", secretAccessKey: "YOUR_SECRET_ACCESS_KEY", region: "us-east-1", model: "anthropic.claude-3-haiku-20240307-v1:0", modelOptions: { temperature: 0.7, }, }); const stream = await model.invoke( { messages: [{ role: "user", content: "Hello, what is AWS Bedrock?" }], }, { streaming: true }, ); let fullText = ""; for await (const chunk of stream) { // Use the type guard to check if the chunk is a delta if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); // Print each part of the response as it arrives } } } console.log("\n--- Full Response ---"); console.log(fullText); ``` This code processes a stream of `AgentResponseChunk` objects. Each chunk contains a delta of the response, which is accumulated to form the complete text. ## Supported Models AWS Bedrock provides access to a wide variety of foundation models from leading AI companies like Anthropic, Cohere, Meta, Stability AI, and Amazon. You can specify the desired model using its unique `modelId`. Some commonly used model families include: - Anthropic Claude: `anthropic.claude-3-sonnet-20240229-v1:0`, `anthropic.claude-3-haiku-20240307-v1:0` - Meta Llama: `meta.llama3-8b-instruct-v1:0` - Amazon Titan: `amazon.titan-text-express-v1` For a complete and up-to-date list of available models and their corresponding IDs, please refer to the [official AWS Bedrock documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html). ## Summary The `@aigne/bedrock` package offers a streamlined way to integrate powerful foundation models from AWS Bedrock into your AIGNE applications. By following the configuration steps and usage patterns outlined in this guide, you can efficiently build and deploy AI-driven features. For more advanced topics, such as tool usage and structured outputs, please refer to the [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) documentation. --- ## Model Configuration URL: https://www.arcblock.io/en/docs/aigne-framework/models-configuration-9dc03e/ To integrate and utilize the various AI models within the AIGNE Framework, you must first configure the necessary credentials, primarily through environment variables. This ensures secure and proper authentication with the respective third-party services. This guide provides the specific environment variables required for each supported model provider. ## General Usage To use a specific model, you typically need to set two primary environment variables: 1. `MODEL`: Specifies the model identifier, often prefixed with the provider's name (e.g., `openai:gpt-4o`). 2. `[PROVIDER]_API_KEY`: The unique API key for that provider (e.g., `OPENAI_API_KEY`). You can set these variables in your shell before running your application. **Set environment variables** ```bash export MODEL=openai:gpt-4o export OPENAI_API_KEY="your_api_key_here" # Then run your AIGNE application node your-app.js ``` ## Provider Configurations Below is a detailed list of the required environment variables for each supported model provider. Replace the placeholder values with your actual credentials. ### OpenAI To connect to OpenAI models like GPT-4o, set the following variables: **OpenAI Configuration** ```bash export MODEL="openai:gpt-4o" export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` ### Anthropic For Anthropic's Claude models, configure the following: **Anthropic Configuration** ```bash export MODEL="anthropic:claude-3-7-sonnet-latest" export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY" ``` ### Google Gemini To use Google's Gemini models, set these variables: **Gemini Configuration** ```bash export MODEL="gemini:gemini-2.0-flash" export GEMINI_API_KEY="YOUR_GEMINI_API_KEY" ``` ### AWS Bedrock For models hosted on AWS Bedrock, you need to provide your AWS credentials and the target region. **AWS Bedrock Configuration** ```bash export MODEL="bedrock:us.amazon.nova-premier-v1:0" export AWS_ACCESS_KEY_ID="YOUR_AWS_ACCESS_KEY_ID" export AWS_SECRET_ACCESS_KEY="YOUR_AWS_SECRET_ACCESS_KEY" export AWS_REGION="YOUR_AWS_REGION" ``` ### DeepSeek To use DeepSeek models, configure the following API key: **DeepSeek Configuration** ```bash export MODEL="deepseek/deepseek-chat" export DEEPSEEK_API_KEY="YOUR_DEEPSEEK_API_KEY" ``` ### Doubao For Doubao models, set the following environment variable: **Doubao Configuration** ```bash export MODEL="doubao-seed-1-6-250615" export DOUBAO_API_KEY="YOUR_DOUBAO_API_KEY" ``` ### Ideogram For Ideogram's image generation models, configure your API key as shown: **Ideogram Configuration** ```bash export MODEL="ideogram-v3" export IDEOGRAM_API_KEY="YOUR_IDEOGRAM_API_KEY" ``` ### Ollama When using a locally hosted Ollama instance, you need to specify the model name and the API endpoint. The API key is typically a placeholder. **Ollama Configuration** ```bash export MODEL="llama3" export OLLAMA_DEFAULT_BASE_URL="http://localhost:11434/v1" export OLLAMA_API_KEY="ollama" ``` ### OpenRouter OpenRouter provides access to various models through a single API. Specify the model with its full path. **OpenRouter Configuration** ```bash export MODEL="openai/gpt-4o" export OPEN_ROUTER_API_KEY="YOUR_OPEN_ROUTER_API_KEY" ``` ### Poe To connect to models via Poe, use the following configuration: **Poe Configuration** ```bash export MODEL="claude-3-opus" export POE_API_KEY="YOUR_POE_API_KEY" ``` ### xAI For xAI's Grok models, set the `XAI_API_KEY` environment variable. **xAI Configuration** ```bash export MODEL="grok-2-latest" export XAI_API_KEY="YOUR_XAI_API_KEY" ``` ### LMStudio For locally hosted models via LMStudio, specify the model name. The API key is typically a placeholder as LMStudio runs locally without authentication by default. **LMStudio Configuration** ```bash export MODEL="llama-3.2-3b-instruct" export LM_STUDIO_API_KEY="lmstudio" ``` ## Summary Properly configuring these environment variables is the foundational step for integrating any model into the AIGNE Framework. This approach keeps your sensitive API keys secure and allows for flexible model selection without changing your application code. For more detailed guides on each provider, please refer to the specific documentation pages, such as [OpenAI](/en/docs/aigne-framework/models-openai-9dc03e/) or [Google Gemini](/en/docs/aigne-framework/models-gemini-9dc03e/). --- ## DeepSeek URL: https://www.arcblock.io/en/docs/aigne-framework/models-deepseek-9dc03e/ This guide provides instructions for configuring and using DeepSeek models within the AIGNE Framework via the `@aigne/deepseek` package. It covers API key setup, model instantiation, and examples for both standard and streaming responses. The `@aigne/deepseek` package provides a direct integration with the DeepSeek API, leveraging its powerful language models. It is designed to be compatible with the AIGNE Framework's `ChatModel` interface, ensuring a consistent development experience. ## Installation To begin, install the necessary packages using your preferred package manager. The `@aigne/core` package is a required peer dependency. **tabs** ```bash npm install @aigne/deepseek @aigne/core ``` **tabs** ```bash yarn add @aigne/deepseek @aigne/core ``` **tabs** ```bash pnpm add @aigne/deepseek @aigne/core ``` ## Configuration The `DeepSeekChatModel` class is the primary interface for interacting with DeepSeek models. It extends the `OpenAIChatModel` and is configured to use DeepSeek's specific API endpoints and authentication methods. Your DeepSeek API key is required for authentication. You can provide it in two ways: ::::steps :::step{title="Directly in the constructor"} Pass the key via the `apiKey` property. ::: :::step{title="Environment variable"} Set the `DEEPSEEK_API_KEY` environment variable. The model will automatically use it if the `apiKey` property is not provided. ::: :::: ### Parameters - **apiKey** `string` — Your DeepSeek API key. If not provided, the client will look for the DEEPSEEK_API_KEY environment variable. - **model** `string` (default: `deepseek-chat`) — The specific DeepSeek model to use for chat completions. Defaults to deepseek-chat. - **modelOptions** `object` — Additional options to pass to the model API, such as temperature, top_p, or max_tokens. - **baseURL** `string` (default: `https://api.deepseek.com`) — The base URL for the DeepSeek API. This should not be changed unless you are using a custom proxy. ## Usage Once configured, the model can be used to generate text completions or stream responses. ### Basic Invocation To generate a standard response, use the `invoke` method. Provide a list of messages, and the method will return a promise that resolves with the complete response from the model. **Basic Usage** ```typescript import { DeepSeekChatModel } from "@aigne/deepseek"; const model = new DeepSeekChatModel({ // Provide API key directly or use environment variable DEEPSEEK_API_KEY apiKey: "your-api-key", // Optional if set in env variables // Specify model version (defaults to 'deepseek-chat') model: "deepseek-chat", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Introduce yourself" }], }); console.log(result); ``` The `result` object contains the generated text and metadata about the model's usage. Example Response ```json { "text": "Hello! I'm an AI assistant powered by DeepSeek's language model.", "model": "deepseek-chat", "usage": { "inputTokens": 7, "outputTokens": 12 } } ``` ### Streaming Responses For real-time applications, you can stream the response from the model. Set the `streaming` option to `true` in the `invoke` method's second argument. This returns an async iterator that yields chunks of the response as they become available. **Streaming Responses** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { DeepSeekChatModel } from "@aigne/deepseek"; const model = new DeepSeekChatModel({ apiKey: "your-api-key", model: "deepseek-chat", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Introduce yourself" }], }, { streaming: true }, ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) fullText += text; if (chunk.delta.json) Object.assign(json, chunk.delta.json); } } console.log(fullText); // Expected output: "Hello! I'm an AI assistant powered by DeepSeek's language model." console.log(json); // Expected output: { model: "deepseek-chat", usage: { inputTokens: 7, outputTokens: 12 } } ``` In this example, the code iterates through the stream, accumulating the text delta from each chunk to build the complete response. Final metadata, such as token usage, is provided in the last chunk. ## Summary This guide has covered the essential steps to install, configure, and use DeepSeek models with the AIGNE Framework. By following these instructions, you can integrate DeepSeek's chat capabilities into your applications for both single-turn and streaming use cases. For more advanced configurations and features, refer to the API reference and other sections in the documentation. --- ## Doubao URL: https://www.arcblock.io/en/docs/aigne-framework/models-doubao-9dc03e/ The `@aigne/doubao` package provides a seamless integration between the AIGNE Framework and Doubao's powerful language and image generation models. This guide provides a complete reference for configuring and utilizing Doubao models within your AIGNE applications. This integration allows developers to leverage Doubao's advanced AI capabilities through the consistent and unified interface of the AIGNE Framework. ## Installation To begin, install the necessary packages using your preferred package manager. You will need both `@aigne/core` and the Doubao-specific package. ```bash npm install @aigne/doubao @aigne/core ``` ```bash yarn add @aigne/doubao @aigne/core ``` ```bash pnpm add @aigne/doubao @aigne/core ``` ## Configuration To use the Doubao models, you must provide an API key. The key can be configured in one of two ways, in order of precedence: ::::steps :::step{title="Direct Instantiation"} Pass the `apiKey` directly in the model's constructor. This method is explicit and overrides any other configuration. ::: :::step{title="Environment Variable"} Set the `DOUBAO_API_KEY` environment variable. The model will automatically use this variable if no key is provided in the constructor. ::: :::: **"Configuration Example"** ```typescript import { DoubaoChatModel } from "@aigne/doubao"; // Method 1: Direct Instantiation const modelWithApiKey = new DoubaoChatModel({ apiKey: "your-doubao-api-key", }); // Method 2: Environment Variable // Set DOUBAO_API_KEY in your .env file or shell // DOUBAO_API_KEY="your-doubao-api-key" const modelFromEnv = new DoubaoChatModel(); ``` The base URL for the Doubao API is pre-configured to `https://ark.cn-beijing.volces.com/api/v3`, but it can be overridden by passing a `baseURL` option to the constructor if necessary. ## Chat Models For conversational tasks, the `DoubaoChatModel` provides an interface to Doubao's language models. It leverages an OpenAI-compatible API structure, ensuring a familiar development experience. ### Basic Usage To perform a chat completion, instantiate `DoubaoChatModel` and use the `invoke` method. **"Basic Chat Completion"** ```typescript import { DoubaoChatModel } from "@aigne/doubao"; const model = new DoubaoChatModel({ apiKey: "your-doubao-api-key", // Or use environment variable model: "doubao-seed-1-6-250615", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Introduce yourself" }], }); console.log(result); ``` Example Response ```json { "text": "Hello! I'm an AI assistant powered by Doubao's language model.", "model": "doubao-seed-1-6-250615", "usage": { "inputTokens": 7, "outputTokens": 12 } } ``` ### Streaming Responses For real-time applications, you can stream the response from the model. Set the `streaming` option to `true` in the `invoke` call and iterate over the resulting stream to process chunks as they arrive. **"Streaming Chat Response"** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { DoubaoChatModel } from "@aigne/doubao"; const model = new DoubaoChatModel({ apiKey: "your-doubao-api-key", model: "doubao-seed-1-6-250615", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Introduce yourself" }], }, { streaming: true } ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); // Print text chunks as they arrive } if (chunk.delta.json) { Object.assign(json, chunk.delta.json); } } } console.log("\n--- Final Data ---"); console.log(fullText); console.log(json); ``` ### Chat Model Parameters The `DoubaoChatModel` constructor accepts the following options: - **apiKey** `string` — Your Doubao API key. If not provided, the DOUBAO_API_KEY environment variable will be used. - **model** `string` (default: `doubao-seed-1-6-250615`) — The specific chat model to use. - **baseURL** `string` (default: `https://ark.cn-beijing.volces.com/api/v3`) — The base URL for the Doubao API endpoint. - **modelOptions** `object` — Additional options passed to the model API, such as temperature, top_p, etc. These are standard OpenAI-compatible parameters. ## Image Models The `DoubaoImageModel` class enables image generation by interfacing with Doubao's image models. ### Basic Usage Instantiate `DoubaoImageModel` and call the `invoke` method with a prompt to generate an image. **"Image Generation"** ```typescript import { DoubaoImageModel } from "@aigne/doubao"; async function generateImage() { const imageModel = new DoubaoImageModel({ apiKey: "your-doubao-api-key", // Or use environment variable model: "doubao-seedream-4-0-250828", }); const result = await imageModel.invoke({ prompt: "A photorealistic image of a cat programming on a laptop", modelOptions: { size: "1024x1024", watermark: false, }, }); console.log(result); } generateImage(); ``` Example Response ```json { "images": [ { "type": "file", "data": "...", // base64 encoded image data "mimeType": "image/jpeg" } ], "usage": { "inputTokens": 0, "outputTokens": 1 }, "model": "doubao-seedream-4-0-250828" } ``` ### Image Model Parameters The `DoubaoImageModel` `invoke` method accepts an input object with the following properties. Note that parameter availability may vary by model. - **prompt** `string` *(required)* — A text description of the desired image(s). - **model** `string` (default: `doubao-seedream-4-0-250828`) — The identifier for the image model to use. - **image** `FileUnion` — For image-to-image models (doubao-seededit-3-0-i2i), provides the input image. - **modelOptions** `object` — An object containing model-specific parameters. - **size** `string` — The desired dimensions of the generated image (e.g., "1024x1024"). - **seed** `number` — A seed value for reproducible results. Supported by doubao-seedream-3-0-t2i and doubao-seededit-3-0-i2i. - **guidanceScale** `number` — Controls how closely the generated image follows the prompt. Supported by doubao-seedream-3-0-t2i and doubao-seededit-3-0-i2i. - **stream** `boolean` (default: `false`) — If true, streams the generation results. Supported by doubao-seedream-4 models. - **watermark** `boolean` (default: `false`) — If false, disables the watermark on the generated image. - **sequentialImageGeneration** `boolean` — Enables sequential image generation. Supported by doubao-seedream-4 models. ### Supported Image Models The following table lists the supported image models and their key characteristics. | Model Family | Supported Models | Key Use Case | |---|---|---| | `doubao-seedream-4` | `doubao-seedream-4-0-250828` | Text-to-Image (T2I) | | `doubao-seedream-3-0-t2i` | (Specific model names vary) | Text-to-Image (T2I) | | `doubao-seededit-3-0-i2i` | (Specific model names vary) | Image-to-Image (I2I) | --- ## Google Gemini URL: https://www.arcblock.io/en/docs/aigne-framework/models-gemini-9dc03e/ This guide provides instructions for configuring and using Google's Gemini models within the AIGNE Framework via the `@aigne/gemini` package. It covers API key setup, model selection, and the specific features available for chat, image, and video generation. The `@aigne/gemini` package offers a seamless integration with Google's advanced AI capabilities, including the Gemini multimodal models and the Imagen text-to-image models, providing a consistent interface within the AIGNE ecosystem. ## Features - Google API Integration: Provides a direct interface to Google's Gemini, Imagen, and Veo API services. - Chat Completions: Supports all available Gemini chat models for conversational AI. - Image Generation: Integrates with both Imagen and Gemini models for image generation and editing. - Video Generation: Leverages Google's Veo models for text-to-video, image-to-video, and frame interpolation tasks. - Multimodal Support: Natively handles inputs combining text, images, audio, and video. - Function Calling: Supports Gemini's function calling capabilities to interact with external tools. - Streaming Responses: Enables real-time data processing for more responsive applications. - Type-Safe: Includes comprehensive TypeScript typings for all APIs and model configurations. ## Installation Install the required packages using your preferred package manager. ```bash npm install @aigne/gemini @aigne/core ``` ## Configuration To authenticate requests, you must provide a Google API key. This can be done by setting an environment variable, which the framework will automatically detect. **Environment Variable** ```bash export GEMINI_API_KEY="your-google-api-key" ``` Alternatively, you can pass the `apiKey` directly in the model's constructor. ## Chat Completions The `GeminiChatModel` class is used for conversational interactions. ### Basic Usage The following example demonstrates how to instantiate and invoke the `GeminiChatModel`. **Chat Model Usage** ```typescript import { GeminiChatModel } from "@aigne/gemini"; const model = new GeminiChatModel({ // API key is optional if the GEMINI_API_KEY environment variable is set. apiKey: "your-api-key", // Specify the model. Defaults to 'gemini-2.0-flash'. model: "gemini-1.5-flash", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Hi there, introduce yourself" }], }); console.log(result); ``` Example Response ```json { "text": "Hello from Gemini! I'm Google's helpful AI assistant. How can I assist you today?", "model": "gemini-1.5-flash", "usage": { "inputTokens": 12, "outputTokens": 18 } } ``` ### Streaming Responses For real-time applications, you can process response chunks as they arrive by enabling streaming. **Streaming Example** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { GeminiChatModel } from "@aigne/gemini"; const model = new GeminiChatModel({ apiKey: "your-api-key", model: "gemini-1.5-flash", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Hi there, introduce yourself" }], }, { streaming: true } ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) fullText += text; if (chunk.delta.json) Object.assign(json, chunk.delta.json); } } console.log(fullText); // Output: "Hello from Gemini! I'm Google's helpful AI assistant. How can I assist you today?" console.log(json); // Output: { model: "gemini-1.5-flash" } ``` ### Chat Model Parameters - **messages** `array` *(required)* — The conversation history. Each message object contains a 'role' and 'content'. - **tools** `array` — A list of available function tools for the model to call. - **toolChoice** `string | object` — Controls how the model uses tools. Can be 'auto', 'required', 'none', or a specific tool. - **responseFormat** `object` — Specifies the desired output format, such as structured JSON. - **model** `string` — The model to use (e.g., 'gemini-1.5-pro', 'gemini-1.5-flash'). - **temperature** `number` — Controls randomness (0-1). Higher values produce more creative responses. - **topP** `number` — Nucleus sampling parameter (0-1). - **topK** `number` — Top-k sampling parameter. - **frequencyPenalty** `number` — Reduces the likelihood of repeating tokens. - **presencePenalty** `number` — Encourages the model to introduce new topics. - **reasoningEffort** `string | number` — For thinking models (e.g., Gemini 2.5), sets the token budget for reasoning. Can be 'minimal', 'low', 'medium', 'high' or a specific token count. - **modalities** `array` — Specifies the desired response modalities, such as ['TEXT'], ['IMAGE'], or ['TEXT', 'IMAGE']. ## Image Generation The `GeminiImageModel` class supports generating and editing images using both specialized Imagen models and multimodal Gemini models. ### Basic Image Generation This example generates an image using an Imagen model. **Image Generation** ```typescript import { GeminiImageModel } from "@aigne/gemini"; const model = new GeminiImageModel({ apiKey: "your-api-key", model: "imagen-4.0-generate-001", // Default Imagen model }); const result = await model.invoke({ prompt: "A serene mountain landscape at sunset with golden light", n: 1, }); console.log(result); ``` Example Response ```json { "images": [ { "type": "file", "data": "iVBORw0KGgoAAAANSUhEUgAA...", "mimeType": "image/png" } ], "usage": { "inputTokens": 0, "outputTokens": 0 }, "model": "imagen-4.0-generate-001" } ``` ### Image Editing with Gemini Models Multimodal Gemini models can edit existing images based on a text prompt. **Image Editing** ```typescript import { GeminiImageModel } from "@aigne/gemini"; const model = new GeminiImageModel({ apiKey: "your-api-key", model: "gemini-2.0-flash-exp", // Gemini model for editing }); const result = await model.invoke({ prompt: "Add vibrant flowers in the foreground", image: [ { type: "url", url: "https://example.com/original-image.png", }, ], n: 1, }); console.log(result.images); // Array of edited images ``` ### Image Model Parameters Parameters vary depending on the model family used. #### Common Parameters | Parameter | Type | Description | |---|---|---| | `prompt` | `string` | Required. A text description of the desired image. | | `model` | `string` | The model to use. Defaults to `imagen-4.0-generate-001`. | | `n` | `number` | The number of images to generate. Defaults to `1`. | | `image` | `array` | For Gemini models, an array of reference images for editing. | #### Imagen Model Parameters | Parameter | Type | Description | |---|---|---| | `seed` | `number` | A random seed for reproducible results. | | `safetyFilterLevel` | `string` | The content moderation safety filter level. | | `personGeneration` | `string` | Controls settings for generating images of people. | | `outputMimeType` | `string` | The output image format (e.g., `image/png`). | | `negativePrompt` | `string` | A description of what to exclude from the image. | | `imageSize` | `string` | The dimensions of the generated image (e.g., "1024x1024"). | | `aspectRatio` | `string` | The aspect ratio of the image (e.g., "16:9"). | #### Gemini Model Parameters | Parameter | Type | Description | |---|---|---| | `temperature` | `number` | Controls randomness (0.0 to 1.0). | | `maxOutputTokens` | `number` | The maximum number of tokens in the response. | | `topP` | `number` | Nucleus sampling parameter. | | `topK` | `number` | Top-k sampling parameter. | | `safetySettings` | `array` | Custom safety settings for content generation. | | `seed` | `number` | A random seed for reproducible results. | | `systemInstruction` | `string` | System-level instructions to guide the model. | ## Video Generation The `GeminiVideoModel` class uses Google's Veo models to generate videos from text or images. ### Basic Video Generation **Text-to-Video** ```typescript import { GeminiVideoModel } from "@aigne/gemini"; const videoModel = new GeminiVideoModel({ apiKey: "your-api-key", model: "veo-3.1-generate-preview", }); const result = await videoModel.invoke({ prompt: "A serene lake with mountains in the background, gentle waves rippling", aspectRatio: "16:9", size: "720p", seconds: "8", }); console.log(result); ``` Example Response ```json { "videos": [ { "type": "file", "data": "base64-encoded-video-data...", "mimeType": "video/mp4", "filename": "timestamp.mp4" } ], "usage": { "inputTokens": 0, "outputTokens": 0 }, "model": "veo-3.1-generate-preview", "seconds": 8 } ``` ### Advanced Video Generation Veo models also support image-to-video and frame interpolation. - Image-to-Video: Provide a `prompt` and a source `image` to animate a static picture. - Frame Interpolation: Provide a `prompt`, a starting `image`, and an ending `lastFrame` to generate a smooth transition between them. **Image-to-Video** ```typescript const result = await videoModel.invoke({ prompt: "Animate this image with gentle movement, clouds drifting slowly", image: { type: "url", url: "https://example.com/input-image.png", }, seconds: "8", }); ``` ### Video Model Parameters - **prompt** `string` *(required)* — A text description of the desired video content. - **model** `string` — The Veo model to use. Defaults to 'veo-3.1-generate-preview'. - **aspectRatio** `string` — Video aspect ratio, either '16:9' (default) or '9:16'. - **size** `string` — Video resolution, either '720p' (default) or '1080p'. - **seconds** `string` — Video duration in seconds: '4', '6', or '8' (default). - **image** `object` — A reference image for image-to-video or the first frame for interpolation. - **lastFrame** `object` — The last frame for frame interpolation. - **referenceImages** `array` — Additional reference images for video generation (Veo 3.1 only). - **negativePrompt** `string` — A description of what to avoid in the video. ## Further Reading For complete API details, refer to the official documentation. - [AIGNE Framework Documentation](https://aigne.io/docs) - [Google GenAI API Reference](https://googleapis.github.io/js-genai/release_docs/) --- ## Ideogram URL: https://www.arcblock.io/en/docs/aigne-framework/models-ideogram-9dc03e/ This document provides a comprehensive guide for developers on integrating and utilizing Ideogram's image generation capabilities within the AIGNE Framework. The `@aigne/ideogram` package provides a seamless interface to Ideogram's API, enabling the generation of high-quality images from textual prompts. This guide will cover the necessary steps for installation, configuration, and usage, complete with code examples and detailed parameter descriptions. For information on other models, refer to the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/). ## Installation To begin, install the `@aigne/ideogram` package into your project. You can use your preferred package manager. **npm** ```bash npm install @aigne/ideogram ``` **yarn** ```bash yarn add @aigne/ideogram ``` **pnpm** ```bash pnpm add @aigne/ideogram ``` ## Configuration Proper configuration is essential for connecting to the Ideogram API. This involves setting up your API key and instantiating the `IdeogramImageModel`. ### API Key Setup The model requires an Ideogram API key for authentication. The recommended and most secure method is to set an environment variable. **.env** ```bash export IDEOGRAM_API_KEY="your-ideogram-api-key" ``` Alternatively, you can pass the `apiKey` directly during the model's instantiation, though this is less secure for production environments. ### Model Instantiation Once the API key is configured, you can import and create an instance of `IdeogramImageModel`. **Instantiating the Model** ```typescript import { IdeogramImageModel } from "@aigne/ideogram"; // The API key will be automatically detected from environment variables. const model = new IdeogramImageModel(); // Alternatively, provide the API key directly. const modelWithApiKey = new IdeogramImageModel({ apiKey: "your-ideogram-api-key", }); ``` ## Basic Usage To generate an image, use the `invoke` method. This method takes an object containing the prompt and any other desired parameters. The only required parameter is `prompt`. **Generating an Image** ```typescript import { IdeogramImageModel } from "@aigne/ideogram"; const model = new IdeogramImageModel(); async function generateImage() { try { const result = await model.invoke({ model: "ideogram-v3", prompt: "A serene mountain landscape at sunset with golden light", }); console.log(JSON.stringify(result, null, 2)); } catch (error) { console.error("Error generating image:", error); } } generateImage(); ``` ### Response Object The `invoke` method returns a promise that resolves to an object containing the generated images and usage metadata. **Example Response** ```json { "images": [ { "type": "url", "url": "https://api.ideogram.ai/generation/...", "mimeType": "image/png" } ], "usage": { "inputTokens": 0, "outputTokens": 0 }, "model": "ideogram-v3" } ``` ## Input Parameters The `invoke` method accepts several parameters to customize the image generation process. - **prompt** `string` *(required)* — The text description of the image you want to generate. - **model** `string` (default: `ideogram-v3`) — Currently, only ideogram-v3 is supported. - **n** `number` (default: `1`) — The number of images to generate. The valid range is from 1 to 8. - **seed** `number` — A random seed for reproducible image generation. Must be an integer between 0 and 2147483647. - **resolution** `string` — The resolution of the generated image (e.g., "1024x1024", "1792x1024"). Refer to the official Ideogram API documentation for all supported resolutions. - **aspectRatio** `string` — The aspect ratio for the image (e.g., "1x1", "16x9"). - **renderingSpeed** `string` (default: `DEFAULT`) — Controls the generation speed and quality. Accepted values are "TURBO", "DEFAULT", or "QUALITY". - **magicPrompt** `string` (default: `AUTO`) — Enables or disables MagicPrompt for prompt enhancement. Accepted values are "AUTO", "ON", or "OFF". - **negativePrompt** `string` — A description of elements to exclude from the generated image. - **styleType** `string` (default: `AUTO`) — Specifies the artistic style. Accepted values are "AUTO", "GENERAL", "REALISTIC", "DESIGN", or "FICTION". - **colorPalette** `object` — An object defining a specific color palette for the generation. - **styleCodes** `string[]` — A list of 8-character hexadecimal codes that represent specific styles. ## Advanced Usage For more control over the output, you can combine multiple optional parameters in a single `invoke` call. **Advanced Image Generation** ```typescript import { IdeogramImageModel } from "@aigne/ideogram"; const model = new IdeogramImageModel(); async function generateAdvancedImage() { try { const result = await model.invoke({ prompt: "A futuristic cityscape with neon lights and flying cars", model: "ideogram-v3", n: 4, resolution: "1792x1024", renderingSpeed: "TURBO", styleType: "FICTION", negativePrompt: "blurry, low quality, distorted", seed: 12345, }); console.log(`Generated ${result.images.length} images.`); result.images.forEach((image, index) => { console.log(`Image ${index + 1}: ${image.url}`); }); } catch (error) { console.error("Error generating image:", error); } } generateAdvancedImage(); ``` ## Default Model Options You can set default parameters during the model's instantiation using the `modelOptions` property. These options will be applied to every `invoke` call unless overridden by parameters in the call itself. **Setting Default Options** ```typescript import { IdeogramImageModel } from "@aigne/ideogram"; const model = new IdeogramImageModel({ modelOptions: { styleType: "REALISTIC", renderingSpeed: "QUALITY", magicPrompt: "ON", }, }); async function generateWithDefaults() { // This call will use the default options defined above. const result = await model.invoke({ prompt: "A photorealistic portrait of an astronaut on Mars", }); console.log(result); } generateWithDefaults(); ``` ## Summary The `@aigne/ideogram` package offers a direct and efficient way to integrate Ideogram's image generation into your applications. By following the configuration steps and utilizing the provided parameters, you can generate high-quality images tailored to your specific needs. For a complete and detailed list of all parameters, supported values, and advanced features, please refer to the official [Ideogram API Reference](https://developer.ideogram.ai/api-reference/api-reference/generate-v3). --- ## LMStudio URL: https://www.arcblock.io/en/docs/aigne-framework/models-lmstudio-9dc03e/ The `@aigne/lmstudio` package provides a model adapter for integrating AIGNE with large language models (LLMs) hosted locally via [LM Studio](https://lmstudio.ai/). This allows developers to leverage the power of local models within the AIGNE framework, offering greater privacy, control, and cost-effectiveness. This guide covers the necessary setup for LM Studio and demonstrates how to use the `LMStudioChatModel` to interact with your local models. For information on other local model providers, see the [Ollama](/en/docs/aigne-framework/models-ollama-9dc03e/) documentation. ## Prerequisites Before using this package, you must complete the following steps: ::::steps :::step{title="Install LM Studio"} Download and install the LM Studio application from the official website: [https://lmstudio.ai/](https://lmstudio.ai/). ::: :::step{title="Download a Model"} Use the LM Studio interface to search for and download a model. Popular choices include variants of Llama 3.2, Mistral, and Phi-3. ::: :::step{title="Start the Local Server"} Navigate to the "Local Server" tab (server icon) in LM Studio, select your downloaded model from the dropdown, and click "Start Server". This will expose an OpenAI-compatible API endpoint, typically at `http://localhost:1234/v1`. ::: :::: ## Installation To add the LMStudio package to your project, run one of the following commands in your terminal: ```bash npm install @aigne/lmstudio ``` ```bash pnpm add @aigne/lmstudio ``` ```bash yarn add @aigne/lmstudio ``` ## Quick Start Once the LM Studio server is running, you can interact with your local model using the `LMStudioChatModel`. The following example demonstrates how to instantiate the model and send a simple request. **Quick Start** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; // 1. Instantiate the model // Ensure the model name matches the one loaded in LM Studio. const model = new LMStudioChatModel({ model: "llama-3.2-3b-instruct", }); // 2. Invoke the model async function main() { try { const response = await model.invoke({ messages: [ { role: "user", content: "What is the capital of France?" } ], }); console.log(response.text); } catch (error) { console.error("Error invoking model:", error); } } main(); ``` If the request is successful, the output will be: ```text The capital of France is Paris. ``` ## Configuration The `LMStudioChatModel` can be configured through its constructor or with environment variables. ### Constructor Options The `LMStudioChatModel` extends the standard `OpenAIChatModel` and accepts the following options: - **model** `string` — The name of the model to use, which must match the model file loaded in the LM Studio server. Defaults to llama-3.2-3b-instruct. - **baseURL** `string` — The base URL of the LM Studio server. Defaults to http://localhost:1234/v1. - **apiKey** `string` — An API key, if you have configured authentication on your LM Studio server. By default, LM Studio runs without authentication, and the key is set to a placeholder value of not-required. - **modelOptions** `object` — Additional options to control model generation. - **temperature** `number` — Controls randomness. Lower values (e.g., 0.2) make the output more deterministic. Defaults to 0.7. - **maxTokens** `number` — The maximum number of tokens to generate in the response. - **topP** `number` — Nucleus sampling parameter. - **frequencyPenalty** `number` — Penalizes new tokens based on their existing frequency. - **presencePenalty** `number` — Penalizes new tokens based on whether they appear in the text so far. Here is an example with custom configuration: **Configuration Example** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; const model = new LMStudioChatModel({ baseURL: "http://localhost:1234/v1", model: "Mistral-7B-Instruct-v0.2-GGUF", modelOptions: { temperature: 0.8, maxTokens: 4096, }, }); ``` ### Environment Variables You can also configure the model by setting environment variables. The constructor options will take precedence if both are provided. - `LM_STUDIO_BASE_URL`: Sets the server's base URL. Defaults to `http://localhost:1234/v1`. - `LM_STUDIO_API_KEY`: Sets the API key. Only necessary if your server requires authentication. **.env** ```bash LM_STUDIO_BASE_URL=http://localhost:1234/v1 # LM_STUDIO_API_KEY=your-key-if-needed ``` ## Features The `LMStudioChatModel` supports several advanced features, including streaming, tool calling, and structured outputs. ### Streaming For real-time applications, you can stream the response as it's being generated. Set the `streaming: true` option in the `invoke` method. **Streaming Example** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; const model = new LMStudioChatModel({ model: "llama-3.2-3b-instruct", }); async function streamStory() { const stream = await model.invoke( { messages: [{ role: "user", content: "Tell me a short story about a robot who discovers music." }], }, { streaming: true } ); for await (const chunk of stream) { if (chunk.type === "delta" && chunk.delta.text) { process.stdout.write(chunk.delta.text.text); } } } streamStory(); ``` ### Tool Calling Many local models support OpenAI-compatible tool calling (also known as function calling). You can provide a list of tools to the model, and it will generate the arguments required to call them. **Tool Calling Example** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; const model = new LMStudioChatModel({ model: "llama-3.2-3b-instruct", }); const tools = [ { type: "function" as const, function: { name: "get_weather", description: "Get the current weather for a specified location.", parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g., San Francisco, CA", }, }, required: ["location"], }, }, }, ]; async function checkWeather() { const response = await model.invoke({ messages: [ { role: "user", content: "What's the weather like in New York?" } ], tools, }); if (response.toolCalls?.length) { console.log("Tool calls:", JSON.stringify(response.toolCalls, null, 2)); } } checkWeather(); ``` ### Structured Output To ensure the model's output conforms to a specific JSON schema, you can define a `responseFormat`. This is useful for tasks that require reliable, machine-readable data. **Structured Output Example** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; const model = new LMStudioChatModel({ model: "llama-3.2-3b-instruct", }); const responseFormat = { type: "json_schema" as const, json_schema: { name: "weather_response", schema: { type: "object", properties: { location: { type: "string" }, temperature: { type: "number" }, description: { type: "string" }, }, required: ["location", "temperature", "description"], }, }, }; async function getWeatherAsJson() { const response = await model.invoke({ messages: [ { role: "user", content: "What is the weather in Paris? Respond in the requested JSON format." } ], responseFormat, }); console.log(response.json); } getWeatherAsJson(); ``` ## Supported Models LM Studio supports a wide variety of GGUF-format models. The exact model name must match what is shown in the LM Studio user interface. Popular compatible models include: | Model Family | Variants | |---|---| | Llama 3.2 | 3B, 8B, 70B Instruct | | Llama 3.1 | 8B, 70B, 405B Instruct | | Mistral | 7B, 8x7B Instruct | | Phi-3 | Mini, Small, Medium Instruct | | CodeLlama | 7B, 13B, 34B Instruct | | Qwen | Various sizes | ## Troubleshooting If you encounter issues, consult the following list of common problems and solutions. | Issue | Solution | |---|---| | Connection Refused | Verify that the LM Studio local server is running and that the `baseURL` in your code is correct. | | Model Not Found | Ensure the `model` name in your code exactly matches the model file name loaded in the LM Studio server. | | Slow Responses | If available, enable GPU acceleration in LM Studio's server settings. Using a smaller model can also help. | | Out of Memory | The model may require more RAM than your system has available. Try using a smaller model or reducing the context length. | ### Error Handling It is good practice to wrap your model calls in a `try...catch` block to handle potential runtime errors, such as network issues. **Error Handling Example** ```typescript import { LMStudioChatModel } from "@aigne/lmstudio"; const model = new LMStudioChatModel(); async function safeInvoke() { try { const response = await model.invoke({ messages: [{ role: "user", content: "Hello!" }], }); console.log(response.text); } catch (error) { if (error.code === "ECONNREFUSED") { console.error("Connection failed. Please ensure the LM Studio server is running."); } else { console.error("An unexpected error occurred:", error.message); } } } safeInvoke(); ``` For more detailed information, refer to the official [LM Studio Documentation](https://lmstudio.ai/docs). To explore other model integrations, you can proceed to the documentation for [AIGNE Hub](/en/docs/aigne-framework/models-aigne-hub-9dc03e/). --- ## Ollama URL: https://www.arcblock.io/en/docs/aigne-framework/models-ollama-9dc03e/ The `@aigne/ollama` package provides a seamless integration between the AIGNE Framework and AI models hosted locally via [Ollama](https://ollama.ai/). This allows developers to leverage a wide variety of open-source language models running on their own hardware, ensuring privacy and offline access to AI capabilities. This guide covers the necessary steps to configure and use the `OllamaChatModel` in your AIGNE applications. For information on other model providers, please see the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/). ![Ollama](https://media.arcblock.io/lib/be/be93853037935e0c.w1600.webp) ## Prerequisites Before using this package, you must have Ollama installed and running on your local machine. You also need to have pulled at least one model. For detailed instructions, please refer to the [official Ollama website](https://ollama.ai/). ## Installation To get started, install the necessary AIGNE packages using your preferred package manager. ::::card-group ::link-card{title="npm" description="```bash npm install @aigne/ollama @aigne/core ```" icon="package"} ::link-card{title="yarn" description="```bash yarn add @aigne/ollama @aigne/core ```" icon="package"} ::link-card{title="pnpm" description="```bash pnpm add @aigne/ollama @aigne/core ```" icon="package"} :::: ## Configuration The `OllamaChatModel` class is the primary interface for interacting with Ollama. When instantiating the model, you can provide several configuration options to customize its behavior. **OllamaChatModel Instantiation** ```typescript import { OllamaChatModel } from "@aigne/ollama"; const model = new OllamaChatModel({ // Specify the Ollama model to use model: "llama3", // The base URL of your local Ollama instance baseURL: "http://localhost:11434/v1", // Optional parameters to pass to the model modelOptions: { temperature: 0.7, }, }); ``` The constructor accepts the following parameters: - **model** `string` (default: `llama3.2`) — The name of the model to use (e.g., llama3, mistral). Ensure the model has been pulled in your Ollama instance. - **baseURL** `string` (default: `http://localhost:11434/v1`) — The base URL for the Ollama API. This can also be configured using the OLLAMA_BASE_URL environment variable. - **apiKey** `string` (default: `ollama`) — A placeholder API key. Ollama does not require authentication by default, but the AIGNE framework requires a non-empty key. It defaults to "ollama" and can be set with the OLLAMA_API_KEY environment variable. - **modelOptions** `object` — An object containing additional parameters to pass to the Ollama API, such as temperature, top_p, etc. These options allow for fine-tuning the model's response generation. ## Basic Usage To run the model, use the `invoke` method. Pass a message payload to generate a chat completion. **Basic Invocation** ```typescript import { OllamaChatModel } from "@aigne/ollama"; const model = new OllamaChatModel({ model: "llama3", modelOptions: { temperature: 0.8, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Explain the importance of local AI models." }], }); console.log(result.text); ``` The `invoke` method returns a promise that resolves to an object containing the model's response. Example Response ```json { "text": "Local AI models are crucial for several reasons. Firstly, they offer enhanced privacy and security since data is processed on-device and never leaves the user's machine...", "model": "llama3" } ``` ## Streaming Responses For applications requiring real-time interaction, you can stream the model's response. Set the `streaming` option to `true` in the `invoke` method. The method will return an async iterator that yields response chunks as they become available. **Streaming Example** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { OllamaChatModel } from "@aigne/ollama"; const model = new OllamaChatModel({ model: "llama3", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Tell me a short story about a robot." }], }, { streaming: true }, ); let fullText = ""; process.stdout.write("Response: "); for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); } } } console.log("\n\n--- End of Stream ---"); console.log("Full text:", fullText); ``` This example demonstrates how to process a stream. Each chunk is a delta of the full response. You can accumulate the text from each chunk to reconstruct the complete message. ## Summary The `@aigne/ollama` package offers a robust and straightforward way to integrate local, open-source models into your AIGNE applications. By following the steps in this guide, you can set up the `OllamaChatModel`, configure it for your needs, and leverage both standard and streaming completions. For further reading on other available models, please see the following guides: - [OpenAI](/en/docs/aigne-framework/models-openai-9dc03e/) - [Google Gemini](/en/docs/aigne-framework/models-gemini-9dc03e/) - [Anthropic](/en/docs/aigne-framework/models-anthropic-9dc03e/) --- ## OpenRouter URL: https://www.arcblock.io/en/docs/aigne-framework/models-open-router-9dc03e/ OpenRouter serves as a unified gateway to a diverse range of AI models from various providers, including OpenAI, Anthropic, and Google. The `@aigne/open-router` package provides a standardized interface for integrating these models into the AIGNE Framework. This allows developers to switch between different models with minimal code changes and implement robust fallback mechanisms. This guide details the process of installing, configuring, and utilizing the `@aigne/open-router` package to leverage multiple AI models. ![OpenRouter](https://media.arcblock.io/lib/52/522f20e263f0943f.w1600.webp) ## Installation To begin, install the `@aigne/open-router` and `@aigne/core` packages. The following commands demonstrate installation using npm, yarn, and pnpm. **npm** ```bash npm install @aigne/open-router @aigne/core ``` **yarn** ```bash yarn add @aigne/open-router @aigne/core ``` **pnpm** ```bash pnpm add @aigne/open-router @aigne/core ``` ## Configuration and Usage The `OpenRouterChatModel` class is the primary interface for interacting with the OpenRouter API. To use it, you must provide your OpenRouter API key. This can be done directly in the constructor via the `apiKey` option or by setting the `OPEN_ROUTER_API_KEY` environment variable. ### Basic Example Below is a standard implementation of the `OpenRouterChatModel` to send a chat request. This example uses Anthropic's `claude-3-opus` model. **Basic Usage** ```typescript import { OpenRouterChatModel } from "@aigne/open-router"; const model = new OpenRouterChatModel({ // Provide API key directly or use environment variable OPEN_ROUTER_API_KEY apiKey: "your-api-key", // Optional if set in env variables // Specify model (defaults to 'openai/gpt-4o') model: "anthropic/claude-3-opus", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Which model are you using?" }], }); console.log(result); ``` The expected output will contain the text response, the model identifier, and token usage metrics. **Output** ```json { "text": "I am currently using the anthropic/claude-3-opus model, accessed through OpenRouter.", "model": "anthropic/claude-3-opus", "usage": { "inputTokens": 15, "outputTokens": 23 } } ``` ### Constructor Options The `OpenRouterChatModel` is extended from the `@aigne/openai` package's `OpenAIChatModel` and accepts the same constructor options. - **apiKey** `string` — Your OpenRouter API key. If not provided, the client will check for the OPEN_ROUTER_API_KEY environment variable. - **model** `string` (default: `openai/gpt-4o`) — The identifier for the model you wish to use (e.g., anthropic/claude-3-opus). - **fallbackModels** `string[]` — An array of model identifiers to use as fallbacks in case the primary model fails. - **baseURL** `string` (default: `https://openrouter.ai/api/v1`) — The base URL for the OpenRouter API. Can be overridden for testing or proxies. - **modelOptions** `object` — An object containing parameters to pass to the model provider, such as temperature, max_tokens, or top_p. ## Using Multiple Models with Fallbacks A key feature of the `@aigne/open-router` package is the ability to specify fallback models. If the primary model request fails, the system will automatically retry the request with the next model in the `fallbackModels` list. This ensures greater application reliability. **Model Fallbacks** ```typescript import { OpenRouterChatModel } from "@aigne/open-router"; const modelWithFallbacks = new OpenRouterChatModel({ apiKey: "your-api-key", model: "openai/gpt-4o", fallbackModels: ["anthropic/claude-3-opus", "google/gemini-1.5-pro"], // Fallback order modelOptions: { temperature: 0.7, }, }); // Will try gpt-4o first, then claude-3-opus if that fails, then gemini-1.5-pro const fallbackResult = await modelWithFallbacks.invoke({ messages: [{ role: "user", content: "Which model are you using?" }], }); console.log(fallbackResult); ``` ## Streaming Responses For applications requiring real-time interaction, you can enable streaming to process response chunks as they become available. Set the `streaming: true` option in the `invoke` method. The response stream must be iterated over to assemble the complete message. **Streaming Example** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { OpenRouterChatModel } from "@aigne/open-router"; const model = new OpenRouterChatModel({ apiKey: "your-api-key", model: "anthropic/claude-3-opus", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Which model are you using?" }], }, { streaming: true }, ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) fullText += text; if (chunk.delta.json) Object.assign(json, chunk.delta.json); } } console.log(fullText); console.log(json); ``` The final `fullText` and `json` objects will contain the aggregated response data. **Output** ```text I am currently using the anthropic/claude-3-opus model, accessed through OpenRouter. { model: 'anthropic/claude-3-opus', usage: { inputTokens: 15, outputTokens: 23 } } ``` ## Summary The `@aigne/open-router` package simplifies access to a wide array of language models through a unified and resilient interface. By leveraging features like model fallbacks and streaming, you can build more robust and responsive AI applications. For more information on the fundamental concepts of models in the AIGNE Framework, refer to the [Models overview](/en/docs/aigne-framework/models-overview-9dc03e/). --- ## OpenAI URL: https://www.arcblock.io/en/docs/aigne-framework/models-openai-9dc03e/ The `@aigne/openai` package provides a seamless integration with OpenAI's suite of models, allowing developers to leverage services like GPT for chat completions, DALL-E for image generation, and Sora for video creation directly within the AIGNE Framework. This document provides a comprehensive guide to installing, configuring, and using these models. For a broader overview of available model providers, please see the [Models](/en/docs/aigne-framework/models-9dc03e/) section. ## Features The OpenAI integration is designed to be robust and developer-friendly, offering a range of features: - Comprehensive Model Support: Full integration with OpenAI's Chat, Image, and Video generation APIs. - Official SDK: Built on top of the official OpenAI SDK for maximum reliability and compatibility. - Advanced Capabilities: Includes support for function calling, streaming responses, and structured JSON outputs. - Type-Safe: Provides complete TypeScript typings for all model configurations and API responses, ensuring code quality and autocompletion. - Consistent Interface: Adheres to the AIGNE Framework's model interface for uniform implementation across different providers. - Extensive Configuration: Offers detailed options for fine-tuning model behavior to meet specific application needs. ## Installation To integrate OpenAI models into your project, install the `@aigne/openai` package alongside the `@aigne/core` framework. Use the command appropriate for your package manager: **npm** ```bash npm install @aigne/openai @aigne/core ``` **yarn** ```bash yarn add @aigne/openai @aigne/core ``` **pnpm** ```bash pnpm add @aigne/openai @aigne/core ``` ## Chat Model (OpenAIChatModel) The `OpenAIChatModel` class serves as the primary interface for interacting with OpenAI's text-based language models, such as GPT-4o and GPT-4o-mini. ### Configuration When creating an instance of `OpenAIChatModel`, you must provide your OpenAI API key. This can be passed directly in the constructor or set as an environment variable named `OPENAI_API_KEY`. - **apiKey** `string` — Your OpenAI API key. If omitted, the system will look for the OPENAI_API_KEY environment variable. - **baseURL** `string` — An optional base URL for the OpenAI API, useful for connecting through a proxy or an alternative endpoint. - **model** `string` (default: `gpt-4o-mini`) — The identifier of the model to be used for chat completions (e.g., "gpt-4o"). - **modelOptions** `object` — A set of parameters to control the generation process. - **temperature** `number` — Controls the randomness of the output. Lower values produce more deterministic results. - **topP** `number` — An alternative to temperature sampling, known as nucleus sampling. - **frequencyPenalty** `number` — Reduces the likelihood of repeating tokens. - **presencePenalty** `number` — Reduces the likelihood of repeating topics. - **parallelToolCalls** `boolean` (default: `true`) — Enables the model to execute multiple function calls concurrently. - **reasoningEffort** `string | number` — For reasoning models (o1/o3), sets the reasoning effort ('minimal', 'low', 'medium', 'high', or a token count). - **clientOptions** `object` — Additional options passed directly to the underlying OpenAI SDK client for advanced customization. ### Basic Usage The following example shows how to instantiate `OpenAIChatModel` and use the `invoke` method to get a response. **Basic Chat Completion** ```typescript import { OpenAIChatModel } from "@aigne/openai"; const model = new OpenAIChatModel({ // Using an environment variable for the API key is recommended. apiKey: "your-api-key", model: "gpt-4o", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Hello, who are you?" }], }); console.log(result); ``` Example Response ```json { "text": "Hello! How can I assist you today?", "model": "gpt-4o", "usage": { "inputTokens": 10, "outputTokens": 9 } } ``` ### Streaming Responses For real-time applications, you can enable streaming by passing `{ streaming: true }` to the `invoke` method. This returns an async iterator that yields response chunks as they are generated. **Streaming Chat Response** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { OpenAIChatModel } from "@aigne/openai"; const model = new OpenAIChatModel({ apiKey: "your-api-key", model: "gpt-4o", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Hello, who are you?" }], }, { streaming: true }, ); let fullText = ""; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); } } } console.log("\n--- Response Complete ---"); ``` ## Image Model (OpenAIImageModel) The `OpenAIImageModel` class provides an interface for OpenAI's image generation and editing models, such as DALL-E 2, DALL-E 3, and gpt-image-1. ### Configuration The image model is configured similarly to the chat model, requiring an API key and allowing for model-specific options. - **apiKey** `string` — Your OpenAI API key. Defaults to the OPENAI_API_KEY environment variable if not provided. - **baseURL** `string` — An optional base URL for the OpenAI API. - **model** `string` (default: `dall-e-2`) — The image model to use (e.g., "dall-e-3", "gpt-image-1"). - **modelOptions** `object` — Parameters to control the image generation process. Available options vary by model. - **size** `string` — The dimensions of the generated image (e.g., '1024x1024'). - **quality** `string` — Image quality, either 'standard' or 'hd' (DALL-E 3 only). - **style** `string` — The artistic style, either 'vivid' or 'natural' (DALL-E 3 only). - **n** `number` — The number of images to generate. - **clientOptions** `object` — Advanced options passed directly to the underlying OpenAI SDK client. ### Image Generation To generate an image, create an instance of `OpenAIImageModel` and invoke it with a text prompt. **Image Generation** ```typescript import { OpenAIImageModel } from "@aigne/openai"; const imageModel = new OpenAIImageModel({ apiKey: "your-api-key", model: "dall-e-3", modelOptions: { size: "1024x1024", quality: "standard", style: "vivid", }, }); const result = await imageModel.invoke({ prompt: "A futuristic city at sunset with flying cars", }); console.log(result); ``` Example Response ```json { "images": [ { "type": "url", "url": "https://...", "mimeType": "image/png" } ], "usage": { "inputTokens": 0, "outputTokens": 0 }, "model": "dall-e-3" } ``` ### Image Editing Image editing is supported by specific models like `gpt-image-1`. To edit an image, provide both a prompt and a reference image. **Image Editing** ```typescript import { OpenAIImageModel } from "@aigne/openai"; const imageModel = new OpenAIImageModel({ apiKey: "your-api-key", model: "gpt-image-1", }); const result = await imageModel.invoke({ prompt: "Add a rainbow to the sky", image: [ { type: "url", url: "https://example.com/original-image.png", }, ], }); console.log(result.images); // Array of edited images ``` ## Video Model (OpenAIVideoModel) The `OpenAIVideoModel` class enables video generation using OpenAI's Sora models. ### Configuration The video model requires an API key and allows for specifying the model, resolution, and duration. - **apiKey** `string` — Your OpenAI API key. Defaults to the OPENAI_API_KEY environment variable if not provided. - **model** `string` (default: `sora-2`) — The video model to use, either "sora-2" (standard) or "sora-2-pro" (higher quality). - **modelOptions** `object` — Parameters to control the video generation process. - **size** `string` (default: `1280x720`) — Video resolution (e.g., '1280x720' for horizontal, '720x1280' for vertical). - **seconds** `string` (default: `4`) — Video duration in seconds. Accepted values are '4', '8', or '12'. ### Video Generation The following example demonstrates how to generate a short video from a text prompt. **Video Generation** ```typescript import { OpenAIVideoModel } from "@aigne/openai"; const videoModel = new OpenAIVideoModel({ apiKey: "your-api-key", model: "sora-2", modelOptions: { size: "1280x720", seconds: "4", }, }); const result = await videoModel.invoke({ prompt: "A serene lake with mountains in the background, gentle waves rippling", }); console.log(result); ``` Example Response ```json { "videos": [ { "type": "file", "data": "base64-encoded-video-data...", "mimeType": "video/mp4", "filename": "video-id.mp4" } ], "usage": { "inputTokens": 0, "outputTokens": 0 }, "model": "sora-2", "seconds": 4 } ``` ### Image-to-Video Generation You can also generate a video by animating a still image. **Image-to-Video** ```typescript import { OpenAIVideoModel } from "@aigne/openai"; const videoModel = new OpenAIVideoModel({ apiKey: "your-api-key", model: "sora-2", }); const result = await videoModel.invoke({ prompt: "Animate this image with gentle movement", image: { type: "url", url: "https://example.com/input-image.png", }, size: "1280x720", seconds: "8", }); console.log(result.videos); ``` ## Summary This guide has covered the essentials for integrating OpenAI's chat, image, and video models into your AIGNE applications. By using the `@aigne/openai` package, you can easily harness the power of these advanced AI capabilities. For further details, refer to the official [OpenAI API documentation](https://platform.openai.com/docs/api-reference). To explore other supported model providers, please visit the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/). --- ## Overview URL: https://www.arcblock.io/en/docs/aigne-framework/models-overview-9dc03e/ The AIGNE Framework is designed to be model-agnostic, allowing developers to integrate a wide variety of large language models (LLMs) and image generation models from different providers. This is achieved through a standardized adapter system that abstracts the unique APIs of each provider behind a consistent interface. At the core of this system are the `ChatModel` and `ImageModel` agents. These specialized agents act as a bridge between your application's logic and the external AI services. By using these standardized agents, you can switch between model providers with minimal code changes, often only requiring a change in configuration. Each supported provider has a dedicated package (e.g., `@aigne/openai`, `@aigne/anthropic`) that contains the specific implementation for communicating with its API. This section provides a summary of all officially supported model providers. For detailed instructions on how to install, configure, and use a specific provider, please refer to its dedicated documentation page. The following diagram illustrates the architecture of the AIGNE Framework's model abstraction layer: ![Overview](https://media.arcblock.io/lib/25/25e13feac1772cc5.w1600.webp) ## Supported Chat Models The following table lists the chat model providers that are officially supported by the AIGNE Framework. Select a provider to view its detailed integration guide. | Provider | Package | |---|---| | [AIGNE Hub](/en/docs/aigne-framework/models-aigne-hub-9dc03e/) | `@aigne/aigne-hub` | | [Anthropic](/en/docs/aigne-framework/models-anthropic-9dc03e/) | `@aigne/anthropic` | | [AWS Bedrock](/en/docs/aigne-framework/models-bedrock-9dc03e/) | `@aigne/bedrock` | | [DeepSeek](/en/docs/aigne-framework/models-deepseek-9dc03e/) | `@aigne/deepseek` | | [Doubao](/en/docs/aigne-framework/models-doubao-9dc03e/) | `@aigne/doubao` | | [Google Gemini](/en/docs/aigne-framework/models-gemini-9dc03e/) | `@aigne/gemini` | | [LMStudio](/en/docs/aigne-framework/models-lmstudio-9dc03e/) | `@aigne/lmstudio` | | [Ollama](/en/docs/aigne-framework/models-ollama-9dc03e/) | `@aigne/ollama` | | [OpenAI](/en/docs/aigne-framework/models-openai-9dc03e/) | `@aigne/openai` | | [OpenRouter](/en/docs/aigne-framework/models-open-router-9dc03e/) | `@aigne/open-router` | | [Poe](/en/docs/aigne-framework/models-poe-9dc03e/) | `@aigne/poe` | | [xAI](/en/docs/aigne-framework/models-xai-9dc03e/) | `@aigne/xai` | ## Supported Image Models The following table lists the image generation model providers that are officially supported. Select a provider to view its detailed integration guide. | Provider | Package | |---|---| | [AIGNE Hub](/en/docs/aigne-framework/models-aigne-hub-9dc03e/) | `@aigne/aigne-hub` | | [Doubao](/en/docs/aigne-framework/models-doubao-9dc03e/) | `@aigne/doubao` | | [Google Gemini](/en/docs/aigne-framework/models-gemini-9dc03e/) | `@aigne/gemini` | | [Ideogram](/en/docs/aigne-framework/models-ideogram-9dc03e/) | `@aigne/ideogram` | | [OpenAI](/en/docs/aigne-framework/models-openai-9dc03e/) | `@aigne/openai` | --- ## Poe URL: https://www.arcblock.io/en/docs/aigne-framework/models-poe-9dc03e/ The `@aigne/poe` package provides a standardized interface for integrating with [Poe](https://poe.com/), a service that offers access to a wide range of third-party language models, including those from OpenAI, Anthropic, and Google. By leveraging an OpenAI-compatible API endpoint, this package allows you to seamlessly use various models within the AIGNE Framework. This guide provides a step-by-step process for installing, configuring, and utilizing the `PoeChatModel`. For more general information on model integration, refer to the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/) documentation. The following diagram illustrates the data flow from a developer's application through the AIGNE Framework to the Poe service and the underlying language models. ![Poe](https://media.arcblock.io/lib/85/85c0c0191cee3a20.w1600.webp) ## Installation To begin, install the necessary packages using your preferred package manager. You will need both `@aigne/core` and the Poe-specific package. ```bash npm install @aigne/poe @aigne/core ``` ```bash yarn add @aigne/poe @aigne/core ``` ```bash pnpm add @aigne/poe @aigne/core ``` ## Configuration The `PoeChatModel` class is the primary interface for interacting with the Poe API. To instantiate it, you must provide your Poe API key and specify the desired model. Your API key can be set in two ways: 1. Directly in the constructor via the `apiKey` property. 2. As an environment variable named `POE_API_KEY`. - **apiKey** `string` — Your Poe API key. While this is optional in the constructor, the key must be available either here or in the POE_API_KEY environment variable for authentication to succeed. - **model** `string` (default: `gpt-5-mini`) — The identifier for the model you wish to use. Poe provides access to models like claude-3-opus, gpt-4o, etc. If not specified, it defaults to gpt-5-mini. - **modelOptions** `object` — Additional options to pass to the model API, such as temperature, topP, or maxTokens. These parameters are sent directly to the underlying model provider. - **baseURL** `string` (default: `https://api.poe.com/v1`) — The base URL for the Poe API. This should not be changed unless you are using a custom proxy. ## Usage The following examples demonstrate how to create a `PoeChatModel` instance and use it for both standard and streaming chat completions. ### Standard Invocation For simple request-response interactions, use the `invoke` method. This method sends the request and waits for the complete response from the model. **Basic Usage** ```typescript import { PoeChatModel } from "@aigne/poe"; const model = new PoeChatModel({ // Provide API key directly or set the POE_API_KEY environment variable apiKey: "your-poe-api-key", // Specify the desired model available through Poe model: "claude-3-opus", modelOptions: { temperature: 0.7, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Which model are you using?" }], }); console.log(result); ``` The `invoke` method returns a structured response containing the model's output and usage metadata. **Expected Output** ```json { "text": "I'm powered by Poe, using the Claude 3 Opus model from Anthropic.", "model": "claude-3-opus", "usage": { "inputTokens": 5, "outputTokens": 14 } } ``` ### Streaming Responses For real-time applications, you can stream the response as it's generated. Set the `streaming: true` option in the `invoke` call to receive an asynchronous stream of response chunks. **Streaming Example** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { PoeChatModel } from "@aigne/poe"; const model = new PoeChatModel({ apiKey: "your-poe-api-key", model: "claude-3-opus", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Which model are you using?" }], }, { streaming: true }, ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) { fullText += text; process.stdout.write(text); } if (chunk.delta.json) { Object.assign(json, chunk.delta.json); } } } console.log("\n--- Final Assembled Data ---"); console.log("Full Text:", fullText); console.log("Metadata:", json); ``` When iterating through the stream, each chunk provides a delta of the response. The complete text and metadata must be assembled from these individual chunks. **Expected Output** ```text I'm powered by Poe, using the Claude 3 Opus model from Anthropic. --- Final Assembled Data --- Full Text: I'm powered by Poe, using the Claude 3 Opus model from Anthropic. Metadata: { model: "anthropic/claude-3-opus", usage: { inputTokens: 5, outputTokens: 14 } } ``` ## Further Reading - For a complete list of available models and their capabilities, please consult the official [Poe documentation](https://developer.poe.com/docs/server-bots-and-apis). - To understand how models fit into the broader AIGNE architecture, see the [Core Concepts: Models](/en/docs/aigne-framework/developer-guide-core-concepts-models-9dc03e/) page. --- ## xAI URL: https://www.arcblock.io/en/docs/aigne-framework/models-xai-9dc03e/ This guide provides instructions for configuring and using xAI's language models, specifically Grok, within the AIGNE Framework. It covers the installation of the necessary package, API key configuration, model instantiation, and examples of both standard and streaming invocations. The `@aigne/xai` package serves as a direct interface to the xAI API, allowing developers to integrate Grok's capabilities into their applications through the standardized `ChatModel` interface provided by the AIGNE Framework. The following diagram illustrates the interaction between the developer, the `@aigne/xai` package, and the xAI Platform. ![xAI](https://media.arcblock.io/lib/c9/c9fa8a1f15d4066e.w1600.webp) ## Installation To begin, install the `@aigne/xai` package along with the AIGNE core library using your preferred package manager. ::::card-group ::link-card{title="npm" description="```bash npm install @aigne/xai @aigne/core ```" icon="package"} ::link-card{title="yarn" description="```bash yarn add @aigne/xai @aigne/core ```" icon="package"} ::link-card{title="pnpm" description="```bash pnpm add @aigne/xai @aigne/core ```" icon="package"} :::: ## Configuration The `XAIChatModel` class is the primary interface for interacting with the xAI API. To use it, you must configure it with your xAI API key. You can provide the API key in two ways: ::::steps :::step{title="Directly in the constructor"} Pass the key via the `apiKey` property. ::: :::step{title="Environment variable"} Set the `XAI_API_KEY` environment variable. The model will automatically detect and use it. ::: :::: ### Constructor Options When creating an instance of `XAIChatModel`, you can provide the following options: - **apiKey** `string` — Your xAI API key. If not provided, the system will fall back to the XAI_API_KEY environment variable. - **model** `string` (default: `grok-2-latest`) — The specific xAI model to use for chat completions. Defaults to grok-2-latest. - **baseURL** `string` (default: `https://api.x.ai/v1`) — The base URL for the xAI API. This is pre-configured and typically does not need to be changed. - **modelOptions** `object` — Additional options to pass to the xAI API, such as temperature, topP, etc. ## Basic Usage The following example demonstrates how to instantiate the `XAIChatModel` and invoke it to get a response. **Basic Invocation** ```typescript import { XAIChatModel } from "@aigne/xai"; const model = new XAIChatModel({ // Provide API key directly or use environment variable XAI_API_KEY apiKey: "your-api-key", // Optional if set in env variables // Specify model (defaults to 'grok-2-latest') model: "grok-2-latest", modelOptions: { temperature: 0.8, }, }); const result = await model.invoke({ messages: [{ role: "user", content: "Tell me about yourself" }], }); console.log(result); ``` ### Example Response The `invoke` method returns an object containing the model's response and usage metadata. **Response Object** ```json { "text": "I'm Grok, an AI assistant from X.AI. I'm here to assist with a touch of humor and wit!", "model": "grok-2-latest", "usage": { "inputTokens": 6, "outputTokens": 17 } } ``` ## Streaming Responses For real-time applications, you can stream the response from the model. Set the `streaming: true` option in the `invoke` method to receive data in chunks as it becomes available. **Streaming Example** ```typescript import { isAgentResponseDelta } from "@aigne/core"; import { XAIChatModel } from "@aigne/xai"; const model = new XAIChatModel({ apiKey: "your-api-key", model: "grok-2-latest", }); const stream = await model.invoke( { messages: [{ role: "user", content: "Tell me about yourself" }], }, { streaming: true }, ); let fullText = ""; const json = {}; for await (const chunk of stream) { if (isAgentResponseDelta(chunk)) { const text = chunk.delta.text?.text; if (text) fullText += text; if (chunk.delta.json) Object.assign(json, chunk.delta.json); } } console.log(fullText); console.log(json); ``` ### Streaming Output When iterating through the stream, you can accumulate the text delta to form the complete message and merge the JSON parts to get the final metadata. **Text Output** ```text I'm Grok, an AI assistant from X.AI. I'm here to assist with a touch of humor and wit! ``` **JSON Output** ```json { "model": "grok-2-latest", "usage": { "inputTokens": 6, "outputTokens": 17 } } ``` This concludes the guide on using the `@aigne/xai` package. For more information on other available models, please see the [Models Overview](/en/docs/aigne-framework/models-overview-9dc03e/). --- ## Overview URL: https://www.arcblock.io/en/docs/aigne-framework/overview-9dc03e/ The AIGNE Framework is a functional AI application development framework designed to simplify and accelerate the process of building scalable, agentic AI applications. It combines functional programming concepts, robust artificial intelligence capabilities, and a modular design to provide a structured environment for developers. This document provides a high-level overview of the AIGNE Framework's architecture, core components, and key features. It also serves as a navigational guide, directing you to the appropriate documentation path based on your technical background and objectives. ## Core Architecture The framework is architecturally designed around a central orchestrator, known as the `AIGNE`, which manages the lifecycle and interactions of various specialized components called `Agents`. Agents are the fundamental units of work, designed to perform specific tasks. They can be composed into teams to handle complex workflows. The following diagram illustrates the relationship between these core components: ![Overview](https://media.arcblock.io/lib/25/25e13feac1772cc5.w1600.webp) - AIGNE: The central execution engine responsible for managing the lifecycle of agents, orchestrating their interactions, and handling the overall execution flow. It is instantiated with a configuration that can include models, agents, and skills. - Agents: The fundamental building blocks of the framework. An agent is an autonomous unit that performs a specific task. The framework provides several specialized agent types, including `AIAgent` for interacting with language models, `TeamAgent` for coordinating multiple agents, and `FunctionAgent` for executing custom code. - Models: Abstractions that interface with external AI model providers like OpenAI, Anthropic, and Google. These are used by agents to leverage the power of large language models (LLMs) and image generation models. - Skills: Reusable capabilities, often represented as functions or other agents, that can be attached to an agent to extend its functionality. ## Key Features The AIGNE Framework is equipped with a comprehensive set of features to support the development of sophisticated AI applications. ::::card-group ::link-card{title="Modular Design" description="A clear modular structure allows developers to organize code effectively, improving development efficiency and simplifying maintenance." icon="box"} ::link-card{title="Multiple AI Model Support" description="Built-in support for a wide range of mainstream AI models, including those from OpenAI, Google, and Anthropic, with an extensible design to support additional models." icon="bot"} ::link-card{title="Flexible Workflow Patterns" description="Natively supports various workflow patterns such as sequential, concurrent, and routing to meet complex application requirements." icon="git-merge"} ::link-card{title="TypeScript Support" description="Provides comprehensive TypeScript type definitions, ensuring type safety and enhancing the overall developer experience." icon="file-text"} ::link-card{title="Code Execution" description="Supports the execution of dynamically generated code within a secure sandbox, enabling powerful automation capabilities." icon="terminal"} ::link-card{title="MCP Protocol Integration" description="Seamlessly integrates with external systems and services through the Model Context Protocol (MCP)." icon="zap"} :::: ## How to Use These Docs To accommodate different needs, this documentation is divided into two primary paths. Please select the path that best aligns with your role and goals. ::::card-group :::action-card{title="Developer Guide" description="For engineers and developers. This guide provides technical deep-dives, code-first examples, API references, and everything you need to build, test, and deploy agentic applications with the AIGNE Framework." icon="code"} ::action{label="Start Building" href="/en/docs/aigne-framework/developer-guide-getting-started-9dc03e/" variant="primary"} ::: :::action-card{title="User Guide" description="For non-technical users, product managers, and business stakeholders. This guide explains the core concepts of AI agents and workflows in plain language, focusing on potential applications and business outcomes without technical jargon." icon="user"} ::action{label="Learn Concepts" href="/en/docs/aigne-framework/user-guide-9dc03e/" variant="primary"} ::: :::: ## Summary This overview has introduced the AIGNE Framework, its core architecture, and its primary features. The framework is a comprehensive toolset for building modern, agent-based AI applications. For your next step, we recommend the following: - Developers: Proceed to the [Getting Started](/en/docs/aigne-framework/developer-guide-getting-started-9dc03e/) guide for a hands-on tutorial. - Non-technical Users: Begin with [What is AIGNE?](/en/docs/aigne-framework/user-guide-what-is-aigne-9dc03e/) for a conceptual introduction. --- ## User Guide URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-9dc03e/ Welcome to the AIGNE User Guide. This guide is designed for a non-technical audience, including business leaders, managers, and anyone curious about how AI can be harnessed to automate complex tasks and streamline business processes. You don't need any programming knowledge to follow along. Our goal is to explain the core concepts of AI agents and workflows in simple, easy-to-understand terms. You will learn what AI agents are, how they can work individually or as a team, and how they can be orchestrated to solve real-world problems, ultimately driving business outcomes. This guide is structured to build your understanding from the ground up: ::::card-group ::link-card{title="What is AIGNE?" description="Start with the fundamentals. This section provides a plain-language introduction to the AIGNE Framework, explaining what AI agents are, the problems they solve, and how they can be used to automate complex tasks." icon="brain" href="/en/docs/aigne-framework/user-guide-what-is-aigne-9dc03e/"} ::link-card{title="Understanding Agents" description="Discover the different roles agents can play. We use simple analogies to explain their functions, from a single digital assistant to a highly coordinated team of specialists, without any technical jargon." icon="users" href="/en/docs/aigne-framework/user-guide-understanding-agents-9dc03e/"} ::link-card{title="Common Workflows" description="See how agents collaborate to achieve a goal. This section illustrates common patterns of agent teamwork using high-level diagrams, showing how information and tasks flow through the system." icon="flag" href="/en/docs/aigne-framework/user-guide-common-workflows-9dc03e/"} :::: By the end of this guide, you will have a solid conceptual grasp of how AIGNE can be applied to create powerful automated solutions for your business. To get started, we recommend beginning with [What is AIGNE?](/en/docs/aigne-framework/user-guide-what-is-aigne-9dc03e/). --- ## Common Workflows URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-common-workflows-9dc03e/ In the AIGNE Framework, a single agent can perform a specific task. However, the true power of the system is realized when multiple agents collaborate to solve more complex problems. Just like members of a team, agents can be organized to work together in structured ways. These patterns of collaboration are called "workflows." Workflows define how tasks and information flow between different agents to achieve a larger goal. By arranging agents in different patterns, we can create sophisticated automated processes for various business needs. The diagram below illustrates three fundamental workflow patterns. ![Common Workflows](https://media.arcblock.io/lib/a0/a040fd84b475bf19.w1600.webp) This guide introduces the most common workflows you'll encounter. Understanding these patterns will help you visualize how agents can automate complex, multi-step processes for you. Explore the detailed explanations for each workflow to learn more about their specific use cases and benefits. ::::card-group ::link-card{title="Sequential Tasks" description="Like an assembly line, agents complete tasks one after another, passing their work to the next agent in line. This is ideal for processes that must happen in a specific order." icon="list" href="/en/docs/aigne-framework/user-guide-common-workflows-sequential-tasks-9dc03e/"} ::link-card{title="Parallel Tasks" description="To get things done faster, multiple agents can work on different parts of a job at the same time. Their individual results are then combined to form a complete solution." icon="git-branch" href="/en/docs/aigne-framework/user-guide-common-workflows-parallel-tasks-9dc03e/"} ::link-card{title="Decision-Making" description="Just like a manager, one agent can analyze an incoming request and intelligently route it to the most suitable specialist agent to handle the job." icon="git-merge" href="/en/docs/aigne-framework/user-guide-common-workflows-decision-making-9dc03e/"} :::: By combining these fundamental patterns, you can build powerful and autonomous systems tailored to your specific needs. Click on any card to dive deeper into how each workflow operates. --- ## Decision-Making URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-common-workflows-decision-making-9dc03e/ Illustrates a scenario where a 'manager' agent analyzes a request and decides which specialized agent is best suited to handle the task. ## Overview In many real-world scenarios, a single AI agent isn't enough. Complex problems often require a team of specialized agents, each an expert in a specific domain. The Decision-Making workflow, also known as a Router or Triage pattern, addresses this by introducing a "manager" agent. The manager agent's sole responsibility is to analyze an incoming request, understand its intent, and route it to the most appropriate specialist agent in the team. This is similar to a customer service dispatcher who listens to a customer's problem and connects them with the right department—be it technical support, billing, or sales. This pattern creates a more efficient and intelligent system. Instead of a single, generalist agent trying to do everything, you have a coordinated team where each member excels at its designated task. ## How It Works The workflow begins when a user submits a request. The manager agent, acting as the central router, receives this request. Based on its instructions and the available "tools" (the specialist agents), it decides which specialist is best equipped to handle the query. The request is then handed off to the chosen specialist, which processes it and produces the final output. For example, if a user asks, "What's the status of my order?", the manager agent would route the query to the "Order Status" agent. If the user asks, "How do I reset my password?", it would be routed to the "Account Support" agent. ![Decision-Making](https://media.arcblock.io/lib/57/571920bc1cdd7e22.w1600.webp) ## Use Cases This workflow is highly effective for: - Intelligent Customer Support: Automatically routing customer queries to the correct department (e.g., Technical Support, Billing, Sales). - Multi-functional Assistants: Creating a single assistant that can delegate tasks like scheduling, data analysis, or content creation to different specialized agents. - Content Moderation: Classifying incoming content and sending it to different moderation queues based on its nature (e.g., spam, hate speech, inappropriate content). - Complex Query Processing: Breaking down a complex query into sub-tasks and routing each to a specific agent for processing. ## Summary The Decision-Making workflow is a powerful pattern for orchestrating a team of specialized AI agents. By using a manager agent to triage and route tasks, you can build more sophisticated, scalable, and efficient AI applications that leverage the strengths of individual, focused agents. To learn more about the technical implementation, see the [Team Agent](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/) and [AI Agent](/en/docs/aigne-framework/developer-guide-agents-ai-agent-9dc03e/) documentation. --- ## Parallel Tasks URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-common-workflows-parallel-tasks-9dc03e/ In some situations, you need to perform several independent tasks at the same time to be more efficient. The parallel tasks workflow is designed for this purpose. It allows multiple AI agents to work simultaneously on the same initial information, with their individual results collected and combined at the end. This approach is like hiring a team of specialists to analyze a business proposal. One specialist might focus on financial viability, another on market trends, and a third on legal risks. They all start with the same proposal and work at the same time, and their final reports are gathered to give a complete picture. This is much faster than if they had to wait for each other to finish. This workflow is managed by an [Agent Team](/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/) configured to operate in parallel mode. For a different approach where tasks are done one after another, see the [Sequential Tasks](/en/docs/aigne-framework/user-guide-common-workflows-sequential-tasks-9dc03e/) workflow. ## How It Works The parallel workflow follows a clear, efficient process for handling tasks that don't depend on each other. The flow is designed to maximize speed by running all agents at once. The following diagram illustrates this process: ![Parallel Tasks](https://media.arcblock.io/lib/6d/6de04053f30946b1.w1600.webp) ::::steps :::step{title="Single Input"} The process begins with a single piece of information, like a document, a user query, or a set of data. ::: :::step{title="Simultaneous Distribution"} The Agent Team takes this input and distributes the exact same information to every agent in the team. ::: :::step{title="Independent Processing"} All agents start working at the same time. Each agent performs its specialized task based on its unique instructions, without waiting for or interacting with the other agents. ::: :::step{title="Result Aggregation"} As each agent finishes its work, its output is collected. The Agent Team then aggregates these individual outputs into a single, combined result. If multiple agents produce an output for the same field, the system typically accepts the result from whichever agent finishes first. ::: :::: This structure ensures that the total time required to complete all tasks is determined by the longest-running agent, rather than the sum of all their times. ## Common Use Cases The parallel workflow is best suited for scenarios where multiple, independent analyses or tasks are needed on the same piece of information, and speed is a priority. ::::card-group ::link-card{title="Multi-Perspective Content Analysis" description="When analyzing a document, one agent could extract key features, another could analyze the emotional tone (sentiment), and a third could identify the target audience. All three tasks can happen at once." icon="search"} ::link-card{title="Parallel Data Queries" description="If you need to search for information across different sources (e.g., a customer database, a product catalog, and a knowledge base), you can dispatch an agent for each source to search simultaneously." icon="database"} ::link-card{title="Competitive Analysis" description="To analyze a competitor's product, one agent could gather recent customer reviews, another could find pricing information, and a third could look up technical specifications, all in parallel." icon="bar-chart"} ::link-card{title="Code Review" description="For a piece of code, one agent can check for security vulnerabilities while another checks for adherence to style guidelines. The feedback is then combined for the developer." icon="code-2"} :::: ## Summary The parallel tasks workflow is a powerful pattern for improving efficiency. By allowing multiple agents to work independently and simultaneously, it significantly reduces the time needed to complete complex jobs that involve several unrelated sub-tasks. This makes it a fundamental workflow for building responsive and powerful AI applications. To see how agents can work together in a different way, read about the [Sequential Tasks](/en/docs/aigne-framework/user-guide-common-workflows-sequential-tasks-9dc03e/) workflow next. --- ## Sequential Tasks URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-common-workflows-sequential-tasks-9dc03e/ A sequential task workflow processes a series of tasks in a specific, predetermined order. It operates like a digital assembly line, where the output of one step becomes the input for the next. This pattern is ideal for multi-stage processes where each step builds upon the work of the previous one. In the AIGNE Framework, this is managed by a `TeamAgent` configured to run in `sequential` mode. Each agent in the team completes its task before passing the result along, ensuring a logical and orderly progression from start to finish. The following diagram illustrates this sequential workflow: ![Sequential Tasks](https://media.arcblock.io/lib/8f/8f8e851e70ebba56.w1600.webp) ## How It Works Imagine a request entering the workflow. 1. The first agent in the sequence receives the initial input and processes it. 2. Once complete, its output is combined with the original input. 3. This combined result is then passed to the second agent in the sequence. 4. This handoff process continues down the line until the final agent completes its task. 5. The output from the last agent is the final result of the entire workflow. This ensures that each agent has the full context of the work done by all preceding agents, allowing for the creation of complex and sophisticated pipelines. ## Common Use Cases Sequential workflows are highly effective for tasks that require a structured, step-by-step approach. - Content Generation Pipeline: An initial agent brainstorms a topic, a second agent writes a draft, a third agent proofreads it, and a final agent formats it for publication. - Data Processing (ETL): One agent extracts data from a source, another transforms it into a standardized format, and a third loads it into a database. - Customer Inquiry Escalation: A frontline agent answers a basic customer question. If the issue is complex, it passes the conversation history to a specialized technical support agent for resolution. - Report Generation: An agent gathers raw data, a second agent analyzes it and generates key insights, and a third agent compiles the findings into a formatted report. ## Summary The sequential tasks workflow provides a reliable and structured way to automate complex, multi-step processes. By chaining agents together, you can build powerful and consistent automation pipelines where the order of operations is critical to achieving the desired outcome. For tasks that can be performed simultaneously, consider the [Parallel Tasks](/en/docs/aigne-framework/user-guide-common-workflows-parallel-tasks-9dc03e/) workflow to improve efficiency. --- ## Understanding Agents URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-understanding-agents-9dc03e/ In the AIGNE framework, an "agent" is the fundamental building block for getting work done. Think of an agent as a specialized digital worker, hired to perform a specific task. Each agent has a clear role and a set of skills. Just like in a real-world team, you can assign a single task to one agent or assemble a team of agents to tackle a more complex project. The core principle is to break down a large problem into smaller, manageable tasks and assign each task to an agent best suited for the job. This approach allows for clarity, efficiency, and the ability to build sophisticated automated workflows. This section provides a conceptual overview of the different roles agents can play. The following diagram illustrates a common workflow where a manager agent coordinates several specialist agents to fulfill a user's request. ![Understanding Agents](https://media.arcblock.io/lib/b4/b43e96b12ad1c80a.w1600.webp) For more detailed explanations, please refer to the following pages: - [Basic Agents](/en/docs/aigne-framework/user-guide-understanding-agents-basic-agents-9dc03e/): Learn about individual agents as standalone workers. - [Agent Teams](/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/): Discover how multiple agents can collaborate to solve complex problems. ### Roles Agents Can Play To better understand their function, we can use analogies to describe the common types of agents and the roles they fulfill within the system. ::::card-group ::link-card{title="The Specialist" description="This is the most common type of agent, often powered by an AI model. It's like an expert you hire for a specific cognitive task, such as a writer, translator, or analyst. You give it instructions and a piece of information, and it produces a result based on its expertise. For example, you could ask it to summarize a long article or draft a professional email." icon="user"} ::link-card{title="The Project Manager" description="This agent doesn't perform the tasks itself but excels at coordinating other agents. Like a real project manager, it takes a complex goal, breaks it down into smaller steps, and delegates those steps to the appropriate specialist agents. It ensures the work flows in the correct order and that the final result is assembled correctly." icon="users"} ::link-card{title="The Tool User" description="Some agents are designed to operate specific tools. This could be a calculator for performing mathematical operations, a tool that searches a database, or one that connects to an external service like a weather API. These agents are reliable and predictable, executing a precise function every time they are called." icon="wrench"} ::link-card{title="The Data Clerk" description="This agent specializes in formatting and reorganizing information. It can take data in one structure and transform it into another. For instance, it could extract specific details from a customer email and format them into a structured record that can be saved in a database, much like a clerk transferring information from a paper form to a spreadsheet." icon="file"} :::: ### Summary By understanding agents as digital workers with specialized roles, you can begin to see how they can be combined to automate complex processes. A single agent can be a powerful tool for a specific task, but the true potential of the AIGNE framework is realized when you assemble a team of agents, each contributing its unique skills to achieve a common goal. To learn more about how these concepts are put into practice, continue to the next sections. - [Basic Agents](/en/docs/aigne-framework/user-guide-understanding-agents-basic-agents-9dc03e/): Explore how individual agents function. - [Agent Teams](/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/): See how to orchestrate multiple agents for complex workflows. --- ## Agent Teams URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/ While a single, specialized agent is useful for a specific task, some problems are too large or complex for one agent to handle alone. Just as in a human organization, when a task requires multiple steps or diverse skills, you assemble a team. In AIGNE, an Agent Team is a group of agents organized to collaborate on solving a larger goal. Think of it this way: if a [Basic Agent](/en/docs/aigne-framework/user-guide-understanding-agents-basic-agents-9dc03e/) is a specialist like a graphic designer, an Agent Team is the entire marketing department, including a copywriter, a strategist, and the designer, all working together on a campaign. ## How Agent Teams Collaborate Agent Teams can be configured to work together in different ways, depending on the nature of the task. The two primary modes of collaboration are sequential and parallel. ### Sequential Workflow: The Assembly Line In a sequential workflow, agents execute tasks one after another in a specific order. The output of the first agent becomes the input for the second agent, and so on, much like an assembly line. This approach is ideal for processes where each step depends on the completion of the previous one. For example, to write a blog post, a team might work as follows: ::::steps :::step{title="Researcher Agent:"} Gathers information and key facts about a topic. ::: :::step{title="Writer Agent:"} Takes the research and drafts the blog post. ::: :::step{title="Editor Agent:"} Reviews the draft for grammar and style, and provides the final version. ::: :::: ### Parallel Workflow: The Brainstorming Session In a parallel workflow, all agents in the team work on the same initial input simultaneously. Each agent performs its specialized task independently, and their individual outputs are then combined to form a final result. This is similar to a brainstorming session where different experts contribute their unique perspectives on a problem at the same time. For example, to analyze market sentiment, a team could work in parallel: - Input: A company's name. - Social Media Agent: Scans Twitter for mentions. - News Agent: Searches for recent news articles. - Financial Agent: Looks up recent stock performance. - Output: All three reports are combined into a single, comprehensive market analysis. ### Reflection: The Quality Assurance Loop A more advanced pattern is "reflection," which introduces a quality control step. In this model, the team completes its task, and then a special Reviewer Agent examines the output. - If the work meets the required standard, the Reviewer approves it, and the process is complete. - If the work is not satisfactory, the Reviewer provides feedback and sends it back to the team for another attempt. This loop continues until the output is approved or a maximum number of attempts is reached. It ensures a higher quality result by building a review-and-refine cycle directly into the workflow. The diagram below illustrates these three primary collaboration patterns. ![Agent Teams](https://media.arcblock.io/lib/09/09c46e20ffc6024e.w1600.webp) ## Summary By organizing agents into teams, you can automate more complex, multi-step workflows. This collaborative approach allows for building sophisticated solutions that mirror real-world business processes, from content creation pipelines to data analysis and quality assurance checks. To see these concepts in action, explore our guides on [Common Workflows](/en/docs/aigne-framework/user-guide-common-workflows-9dc03e/), which provide practical examples of agent teams solving real problems. For technical details on implementation, developers can refer to the [Team Agent documentation](/en/docs/aigne-framework/developer-guide-agents-team-agent-9dc03e/). --- ## Basic Agents URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-understanding-agents-basic-agents-9dc03e/ Think of a basic agent as a specialized digital assistant, like a helpful chatbot or a focused data entry clerk. Each agent is designed to perform one specific type of task and do it well. It operates based on a clear set of instructions, receives a specific input to work on, and produces a result. These single-purpose agents are the fundamental building blocks of AIGNE. While simple on their own, they can be combined to handle much more complex workflows, which we will explore in the [Agent Teams](/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/) section. ## The Anatomy of an Agent Every basic agent, regardless of its function, is defined by a few core components. Understanding these parts helps clarify how an agent knows what to do. ::::card-group ::link-card{title="Instructions" description="This is the agent's permanent rulebook or job description. It's a detailed guide that tells the agent who it is, what its purpose is, and how it should behave. For example, the instructions for a customer service agent might be: \"You are a friendly and helpful assistant. Your goal is to answer customer questions accurately.\"" icon="book-open"} ::link-card{title="Input" description="This is the specific piece of information or the task you give the agent at a particular moment. If the agent is a chatbot, the input would be the user's question, like \"What are your business hours?\"." icon="arrow-right"} ::link-card{title="Output" description="This is the result the agent produces after processing the input according to its instructions. For the chatbot example, the output would be the answer: \"Our business hours are from 9 AM to 5 PM, Monday to Friday.\"" icon="arrow-left"} ::link-card{title="Skills" description="These are special tools or abilities an agent can use to perform its task. For instance, a \"Weather Agent\" might have a skill that allows it to access real-time weather data from an external service." icon="sparkles"} :::: ## How an Agent Works The process is straightforward. A user provides an input to an agent. The agent then consults its core instructions to understand the context and rules, uses any skills it might have if necessary, and generates an output. ![Basic Agents](https://media.arcblock.io/lib/df/dff4279eef7546f8.w1600.webp) ## Example: A Simple Chat Agent Let's look at a practical example of a "Chat Agent." This agent is designed to be a helpful assistant that answers questions. Its configuration would look something like this: | Property | Value | Description | |---|---|---| | Name | `chat` | A simple identifier for the agent. | | Description | `Chat agent` | A brief explanation of its purpose. | | Instructions | `You are a helpful assistant...` | This tells the agent to be friendly and informative. | | Input Key | `message` | The agent expects the user's question to be labeled as "message". | | Output Key | `message` | The agent will label its answer as "message". | When you send this agent an input like `message: "How does an agent work?"`, it follows its instructions to be helpful and provides a clear, informative answer based on its programming. ## Summary A basic agent is a single-task digital worker defined by its instructions, the input it receives, and the output it produces. They are the essential, foundational components of AIGNE. While powerful for specific tasks, their true potential is unlocked when they are assembled into [Agent Teams](/en/docs/aigne-framework/user-guide-understanding-agents-agent-teams-9dc03e/) to tackle more complex challenges. --- ## What is AIGNE? URL: https://www.arcblock.io/en/docs/aigne-framework/user-guide-what-is-aigne-9dc03e/ AIGNE (pronounced `[ˈei dʒən]`, like "agent" without the "t") is a functional framework for developing AI applications. It is designed to simplify and accelerate the process of building scalable, modern applications by combining functional programming, modular design, and powerful artificial intelligence capabilities. The core concept of AIGNE is the use of agents—specialized AI assistants—that can be organized into teams to automate complex, multi-step tasks. Instead of relying on a single, monolithic AI, AIGNE provides the structure to create a digital workforce where different agents collaborate, each handling a specific part of a larger problem. This document provides a plain-language introduction to the AIGNE Framework, explaining what AI agents are, the problems they solve, and how they work together to automate sophisticated workflows. ## What is an AI Agent? An AI Agent is a specialized digital assistant designed to perform a specific function. Each agent operates based on a given set of instructions and can be equipped with specific tools to execute its tasks. Unlike a general-purpose chatbot, an AIGNE agent is an expert in a narrow domain. Consider agents as individual members of a highly efficient project team: - The Researcher: An agent that can access external information sources to gather data. - The Writer: An agent that processes raw information and drafts a structured document. - The Coder: An agent capable of writing and executing code to perform a technical function. - The Analyst: An agent that can interpret data, identify patterns, and provide insights. While a single agent is effective for simple, defined tasks, the primary strength of the AIGNE Framework is its ability to orchestrate multiple agents into a cohesive team to achieve a complex objective. ## The Problem AIGNE Solves A single Large Language Model (LLM) is a powerful tool for tasks like answering questions or generating text. However, its capabilities are limited when faced with processes that require multiple distinct steps, different skill sets, or information from various sources. For instance, a request such as, "Analyze our latest sales report, compare it to public competitor performance data, and draft a presentation for the marketing team," would be challenging for a standard chatbot. This process involves several discrete stages: ::::steps :::step{title="Data Analysis:"} Reading and interpreting the internal sales report. ::: :::step{title="External Research:"} Locating and extracting competitor performance data. ::: :::step{title="Synthesis:"} Comparing the two datasets to identify key insights. ::: :::step{title="Content Creation:"} Structuring the findings into a coherent presentation. ::: :::: AIGNE addresses this by providing a framework to deconstruct such a complex request into manageable sub-tasks. Each sub-task is then assigned to a specialized agent, and the framework manages the flow of information between them, ensuring a complete and accurate final output. ## How Agents Work Together to Automate Tasks AIGNE orchestrates agents into workflows, which are structured processes for executing tasks. By connecting agents, you can automate processes that would otherwise require significant manual coordination. The framework supports several patterns of collaboration, allowing for flexible and powerful automation. The following diagram illustrates how the AIGNE Framework breaks down a complex task and manages a team of agents to produce a final result. ![What is AIGNE?](https://media.arcblock.io/lib/20/20f440d04e947520.w1600.webp) Common workflow patterns include: - Sequential Workflow (Assembly Line): One agent completes its task and passes the result directly to the next agent. This is suitable for processes with a required order of operations, such as gathering data, summarizing it, and then drafting a report. - Parallel Workflow (Teamwork): Multiple agents work on different parts of a task simultaneously to improve efficiency. For example, to analyze customer feedback, one agent could process positive reviews while another processes negative reviews at the same time, with the results aggregated at the end. - Routing Workflow (Manager): A "manager" agent analyzes an incoming request and determines which specialist agent is best equipped to handle it. This pattern is effective for creating intelligent assistants or helpdesks that can address a wide variety of queries. By combining these workflow patterns, developers can construct sophisticated systems to automate a vast range of digital processes. ## Summary AIGNE is a framework for building and managing a digital workforce of specialized AI agents. It provides the tools to: - Decompose complex problems into smaller, well-defined tasks. - Assign each task to an appropriate AI agent with the right skills. - Orchestrate the collaboration between agents to achieve a final, coherent goal. This agent-based approach overcomes the limitations of single AI models, enabling the automation of complex, real-world business processes with greater reliability and precision. To learn more about the different roles agents can play within the system, proceed to the next section. - Next: [Understanding Agents](/en/docs/aigne-framework/user-guide-understanding-agents-9dc03e/) --- ## AIGNE Hub URL: https://www.arcblock.io/en/docs/aigne-hub/ --- ## API Reference URL: https://www.arcblock.io/en/docs/aigne-hub/api-reference-32e774/ This document provides technical specifications for the AIGNE Hub RESTful API. By following this guide, you will understand how to authenticate and interact with the core endpoints for chat completions, image generation, and embeddings, enabling robust backend integrations with your applications. The AIGNE Hub API provides a unified interface to various underlying AI models, abstracting the complexity of individual provider APIs. All requests are authenticated using API keys. The following diagram illustrates the interaction between an application, the AIGNE Hub API, and the underlying AI models. ![API Reference](https://media.arcblock.io/lib/c6/c65f3bf14cf3e416.w1600.webp) For detailed specifications on each endpoint, including request and response schemas, please refer to the specific sub-sections: ::::card-group ::link-card{title="Chat Completions" description="Detailed specification for the chat completions endpoint, including request/response schemas and streaming support." icon="message-square" href="/en/docs/aigne-hub/api-reference-chat-completions-32e774/"} ::link-card{title="Image Generation" description="Reference for the image generation endpoint, covering supported models and parameters for size and quality." icon="image" href="/en/docs/aigne-hub/api-reference-image-generation-32e774/"} ::link-card{title="Embeddings" description="Documentation for creating vector representations of text for use in semantic search and other ML tasks." icon="code" href="/en/docs/aigne-hub/api-reference-embeddings-32e774/"} :::: ::::card-group ::link-card{title="API Authentication" description="Explains how to securely authenticate requests to the AIGNE Hub API using OAuth and API keys." icon="key" href="/en/docs/aigne-hub/api-reference-authentication-32e774/"} :::: ## Endpoints The following table provides a summary of the available API endpoints. | Method | Endpoint | Description | |---|---|---| | `POST` | `/chat/completions` | Generates a response for a given chat conversation. | | `POST` | `/embeddings` | Generates vector embeddings for a given input text. | | `POST` | `/image/generations` | Creates an image based on a text prompt. | | `POST` | `/audio/transcriptions` | Transcribes audio into the input language. | | `POST` | `/audio/speech` | Generates audio from the input text. | | `GET` | `/status` | Checks the availability of the service and models. | ## Summary This section provided an overview of the AIGNE Hub API, covering authentication and a summary of available endpoints. For practical integration, proceed to the detailed documentation for each endpoint. - For building conversational AI: See the [Chat Completions API](/en/docs/aigne-hub/api-reference-chat-completions-32e774/). - For generating images: Explore the [Image Generation API](/en/docs/aigne-hub/api-reference-image-generation-32e774/). - For text analysis and search: Use the [Embeddings API](/en/docs/aigne-hub/api-reference-embeddings-32e774/). --- ## API Authentication URL: https://www.arcblock.io/en/docs/aigne-hub/api-reference-authentication-32e774/ Securely authenticating requests to the AIGNE Hub API is a critical step for programmatic access and integration. This guide provides a clear, step-by-step process for using API keys to authorize your applications, ensuring that all interactions are secure and properly identified. ## Authentication Methods AIGNE Hub primarily uses bearer authentication with API keys for its RESTful API. All API requests must include an `Authorization` header containing a valid API key. This method is straightforward, secure, and aligns with industry best practices for service-to-service communication. ## Generating an API Key Before you can authenticate, you must generate an API key from the AIGNE Hub admin interface. 1. Navigate to the Settings section in your AIGNE Hub instance. 2. Select the API Keys tab. 3. Click the "Generate New Key" button. 4. Provide a descriptive name for your key to help you identify its purpose later (e.g., `dev-server-integration`, `analytics-script-key`). 5. The system will generate a new key. Copy this key immediately and store it in a secure location. For security reasons, the full key will not be shown again after you leave this page. ## Using the API Key To authenticate an API request, include the API key in the `Authorization` header of your HTTP request. The value must be prefixed with the `Bearer `scheme. ### HTTP Header Format ``` Authorization: Bearer ``` Replace `` with the actual key you generated. ### Example Request with cURL Here is an example of how to make an authenticated request to the Chat Completions endpoint using `cURL`. **Authenticated API Request** ```bash curl -X POST https://your-aigne-hub-url/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "model": "aignehub/gpt-3.5-turbo", "messages": [{"role": "user", "content": "Hello!"}] }' ``` ### Example in a Node.js Application When integrating with an application, you will set the `Authorization` header in your HTTP client library. The following example uses the AIGNE Hub SDK, which simplifies this process. **AIGNEHubChatModel.js** ```javascript import { AIGNEHubChatModel } from "@aigne/aigne-hub"; const model = new AIGNEHubChatModel({ baseURL: "https://your-aigne-hub-url", apiKey: "YOUR_API_KEY", // The SDK handles adding the "Bearer " prefix model: "aignehub/gpt-3.5-turbo", }); async function getGreeting() { try { const result = await model.invoke({ messages: [{ role: "user", content: "Hello, AIGNE Hub!" }], }); console.log(result); } catch (error) { console.error("API request failed:", error.message); } } getGreeting(); ``` In this example, the `apiKey` provided to the `AIGNEHubChatModel` constructor is automatically placed into the correct `Authorization` header for all subsequent API calls made by the model instance. ## Security Best Practices - Treat API keys like passwords. Store them securely in a secret manager or as environment variables. Never expose them in client-side code or commit them to version control. - Use different keys for different applications. This practice, known as the principle of least privilege, limits the impact if a single key is compromised. - Rotate keys regularly. Periodically revoke old keys and generate new ones to reduce the risk of unauthorized access from a compromised key. - Monitor API usage. Keep an eye on the analytics dashboard to detect any unusual activity that might indicate a compromised key. ## Summary Authentication to the AIGNE Hub API is handled via API keys included in the `Authorization` header as bearer tokens. By following the generation process and security best practices outlined above, you can ensure secure and reliable programmatic access to all API endpoints. For more information on specific endpoints, please refer to the following sections: - [Chat Completions](/en/docs/aigne-hub/api-reference-chat-completions-32e774/) - [Image Generation](/en/docs/aigne-hub/api-reference-image-generation-32e774/) - [Embeddings](/en/docs/aigne-hub/api-reference-embeddings-32e774/) --- ## Chat Completions URL: https://www.arcblock.io/en/docs/aigne-hub/api-reference-chat-completions-32e774/ This document provides a detailed specification for the Chat Completions API endpoint. By following this guide, you will learn how to generate conversational AI responses, manage streaming, and utilize model-specific parameters for building robust applications. This endpoint is central to creating interactive, text-based experiences. The Chat Completions API enables you to build applications that leverage large language models for a variety of conversational tasks. You provide a series of messages as input, and the model returns a text-based response. ![Chat Completions](https://media.arcblock.io/lib/57/572eeb077b3eebfe.w1600.webp) For related functionalities, refer to the [Image Generation](/en/docs/aigne-hub/api-reference-image-generation-32e774/) and [Embeddings](/en/docs/aigne-hub/api-reference-embeddings-32e774/) API documentation. ## Create Chat Completion Creates a model response for the given chat conversation. `POST /api/chat/completions` ### Request Body - **model** `string` *(required)* (default: `gpt-3.5-turbo`) — ID of the model to use. See the model endpoint compatibility table for details on which models work with the Chat API. - **messages** `array` *(required)* — A list of messages comprising the conversation so far. See below for the message object structure. - **message** `object` — Each message object must have a role and content. - **role** `string` *(required)* — The role of the message's author. Can be system, user, assistant, or tool. - **content** `string or array` *(required)* — The content of the message. This can be a string or an array of content parts for multimodal models (e.g., text and image URLs). - **name** `string` — An optional name for the participant. Provides the model with context about the author of the message. - **tool_calls** `array` — The tool calls generated by the model, such as function calls. - **tool_call_id** `string` — Required if the role is tool. The ID of the tool call that this message is responding to. - **temperature** `number` (default: `1`) — Controls randomness. Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive. Range: 0 to 2. - **top_p** `number` (default: `1`) — Controls diversity via nucleus sampling. 0.5 means half of all likelihood-weighted options are considered. Range: 0.1 to 1. - **stream** `boolean` (default: `false`) — If set to true, partial message deltas will be sent as server-sent events. The stream terminates with a data: [DONE] message. - **max_tokens** `integer` — The maximum number of tokens to generate. The total length of input tokens and generated tokens is limited by the model's context length. - **presence_penalty** `number` (default: `0`) — Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. - **frequency_penalty** `number` (default: `0`) — Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. - **tools** `array` — A list of tools the model may call. Currently, only functions are supported as a tool. - **tool_choice** `string or object` — Controls which (if any) tool is called by the model. Can be 'none', 'auto', 'required', or an object specifying a function to call. - **response_format** `object` — An object specifying the format that the model must output. Setting to { "type": "json_object" } enables JSON mode. ### Examples #### Basic Request This example demonstrates a simple conversation with the model. **cURL Request** ```bash curl --location 'https://your-aigne-hub-instance.com/api/chat/completions' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "model": "gpt-3.5-turbo", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "Hello! Can you explain what AIGNE Hub is in simple terms?" } ] }' ``` #### Streaming Request To receive the response as a stream of events, set the `stream` parameter to `true`. **cURL Stream Request** ```bash curl --location 'https://your-aigne-hub-instance.com/api/chat/completions' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --header 'Accept: text/event-stream' \ --data '{ "model": "gpt-3.5-turbo", "messages": [ { "role": "user", "content": "Write a short story about a robot who discovers music." } ], "stream": true }' ``` ### Response Body #### Standard Response A standard JSON object is returned when `stream` is `false` or not set. - **role** `string` — The role of the author of this message, always 'assistant'. - **content** `string` — The content of the message generated by the model. - **tool_calls** `array` — The tool calls generated by the model, if any. Example Standard Response **Response Body** ```json { "role": "assistant", "content": "AIGNE Hub is a centralized gateway that manages interactions with various AI models from different providers. It simplifies API access, handles billing and credits, and provides analytics on usage and costs, acting as a single point of control for an organization's AI services." } ``` #### Streaming Response When `stream` is `true`, the API returns a stream of `text/event-stream` chunks. Each chunk is a JSON object. - **delta** `object` — A chunk of the message delta. - **role** `string` — The role of the author, typically 'assistant'. - **content** `string` — A partial content of the message. - **tool_calls** `array` — Partial tool call information. - **usage** `object` — Present in the final chunk, contains token usage statistics. - **prompt_tokens** `integer` — Number of tokens in the prompt. - **completion_tokens** `integer` — Number of tokens in the generated completion. - **total_tokens** `integer` — Total number of tokens used in the request. Example Stream Chunks **Event Stream** ```text data: {"delta":{"role":"assistant","content":"Unit "}} data: {"delta":{"content":"734,"}} data: {"delta":{"content":" a sanitation "}} data: {"delta":{"content":"and maintenance "}} data: {"delta":{"content":"robot, hummed..."}} data: {"usage":{"promptTokens":15,"completionTokens":100,"totalTokens":115}} data: [DONE] ``` ## Summary The Chat Completions endpoint is a powerful tool for integrating conversational AI into your applications. It offers flexibility through various parameters, including streaming and tool use, to support a wide range of use cases. For more information on other available API endpoints, please refer to the following documents: ::::card-group ::link-card{title="Image Generation" description="Learn how to generate and manipulate images using AI models." icon="image" href="/en/docs/aigne-hub/api-reference-image-generation-32e774/"} ::link-card{title="Embeddings" description="Understand how to create vector representations of text for machine learning tasks." icon="bot" href="/en/docs/aigne-hub/api-reference-embeddings-32e774/"} :::: --- ## Embeddings URL: https://www.arcblock.io/en/docs/aigne-hub/api-reference-embeddings-32e774/ This document provides a detailed specification for the AIGNE Hub Embeddings API endpoint. By following this guide, you will learn how to convert text into numerical vector representations, a foundational step for tasks like semantic search, text clustering, and similarity analysis. ## Create embedding Generates a vector representation for a given text input. This is useful for machine learning applications that require a numerical representation of text. POST `/api/embeddings` ### Request Body - **model** `string` *(required)* — The ID of the model to use for generating the embeddings. The model must be compatible with embedding tasks. - **input** `string or array` *(required)* — The input text or tokens to embed. This can be a single string, an array of strings, an array of integers (tokens), or an array of integer arrays (batched tokens). ### Example Request Here is an example of how to call the embeddings endpoint using cURL. **Create an embedding request** ```bash curl https://your-aigne-hub-instance.com/api/embeddings \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "model": "text-embedding-3-small", "input": "AIGNE Hub is a unified AI gateway." }' ``` ### Response Body The API returns an object containing the list of embedding data. - **data** `array` *(required)* — An array of embedding objects, where each object corresponds to an input item. - **embedding** `array` *(required)* — The vector representation of the input text, returned as an array of floating-point numbers. - **index** `number` *(required)* — The index of the embedding in the list, corresponding to the order of the input items. - **object** `string` *(required)* — The type of object, which is always embedding. - **model** `string` *(required)* — The model that was used to generate the embeddings. - **object** `string` *(required)* — The type of the top-level object, which is always list. - **usage** `object` *(required)* — An object detailing the token usage for the request. - **prompt_tokens** `number` *(required)* — The number of tokens in the input prompt. - **total_tokens** `number` *(required)* — The total number of tokens consumed by the request. ### Example Response **Example Response** ```json { "object": "list", "data": [ { "object": "embedding", "embedding": [ -0.006929283495992422, -0.005336422007530928, ... -4.547132266452536e-05 ], "index": 0 } ], "model": "text-embedding-3-small", "usage": { "prompt_tokens": 8, "total_tokens": 8 } } ``` ## Summary The Embeddings API provides a straightforward method for converting text into high-dimensional vectors, enabling a wide range of natural language processing applications. For building more complex conversational or generative AI, you may also want to explore the [Chat Completions API](/en/docs/aigne-hub/api-reference-chat-completions-32e774/). --- ## Image Generation URL: https://www.arcblock.io/en/docs/aigne-hub/api-reference-image-generation-32e774/ This document provides the technical specifications for the image generation endpoint. By following this guide, you will be able to integrate AI-powered image creation into your applications by structuring requests, specifying models and parameters, and handling the resulting image data. The AIGNE Hub API allows you to generate new images from a text prompt or edit existing images. For details on other AI functionalities, see the [Chat Completions](/en/docs/aigne-hub/api-reference-chat-completions-32e774/) and [Embeddings](/en/docs/aigne-hub/api-reference-embeddings-32e774/) documentation. ## Create Image Generates an image based on a textual description (prompt). You can also provide an existing image to be edited. Endpoint ```sh POST /api/images/generations ``` This endpoint creates a new image or edits an existing one, returning the image data in the specified format. ### Request Body - **prompt** `string` *(required)* — A detailed text description of the desired image. The maximum length depends on the model, but shorter, precise prompts often yield better results. - **model** `string` (default: `dall-e-2`) — The model ID to use for image generation. If not specified, the system defaults to dall-e-2. Other models like dall-e-3 or Google's gemini models may be available depending on provider configurations. - **image** `string or array` — The source image or images for editing. This can be a URL or a Base64 encoded string. Currently, this parameter is utilized by the gpt-image-1 model for image editing tasks. - **n** `integer` (default: `1`) — The number of images to generate. Must be an integer between 1 and 10. - **size** `string` (default: `1024x1024`) — The desired dimensions of the generated image. Supported sizes depend on the selected model. Common values include 256x256, 512x512, and 1024x1024 for DALL·E 2, and 1024x1024, 1792x1024, or 1024x1792 for DALL·E 3. - **response_format** `string` (default: `url`) — The format in which the generated images are returned. Must be one of url or b64_json. A url will be accessible for one hour, while b64_json provides the image data encoded in Base64. - **quality** `string` (default: `standard`) — The quality of the generated image. Only supported by dall-e-3. Can be standard for faster generation or hd for enhanced detail and higher quality, which may have increased cost. - **style** `string` (default: `vivid`) — The artistic style of the generated image. Only supported by dall-e-3. Can be vivid for hyper-realistic and dramatic results or natural for a more photorealistic and less processed look. ### Response Body The API returns an object containing the creation timestamp and an array of generated image data. - **created** `integer` — A UNIX timestamp indicating when the image generation was initiated. - **data** `array` — An array of objects, where each object contains one generated image. The structure of the objects inside the array depends on the response_format parameter. - **object** `object` — Contains either a url or b64_json field with the image data. - **url** `string` — The URL where the generated image can be accessed. This URL is temporary and will expire. - **b64_json** `string` — The Base64-encoded JSON string of the generated image. ### Examples #### Basic Image Generation This example demonstrates a standard request to generate a single image using the default `dall-e-2` model. **Request** ```bash curl --location 'https://your-aigne-hub-instance.com/api/images/generations' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "prompt": "A photorealistic image of a cat programming on a laptop", "n": 1, "size": "1024x1024" }' ``` The server returns the URL for the generated image. **Response** ```json { "created": 1678886400, "data": [ { "url": "https://example.com/generated-images/image-xyz.png" } ] } ``` #### Generating with DALL·E 3 and Base64 Response This example uses the `dall-e-3` model to create a high-quality, vivid image and returns the result as a Base64 encoded string. **Request** ```bash curl --location 'https://your-aigne-hub-instance.com/api/images/generations' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "model": "dall-e-3", "prompt": "An oil painting of a futuristic city skyline at sunset, with flying cars", "n": 1, "size": "1792x1024", "quality": "hd", "style": "vivid", "response_format": "b64_json" }' ``` The response contains the Base64 data, which can be directly decoded and saved as an image file. **Response** ```json { "created": 1678886400, "data": [ { "b64_json": "iVBORw0KGgoAAAANSUhEUgAAB...rest_of_base64_string" } ] } ``` ## Summary You now have the necessary information to use the image generation endpoint. This includes understanding the request parameters for creating and editing images, as well as handling the different response formats. For further reading on related API functionalities, please refer to the following documents: ::link-card{title="Chat Completions API" icon="message-square" href="/en/docs/aigne-hub/api-reference-chat-completions-32e774/"} Learn how to build conversational experiences with our chat models. ::link-card{title="Embeddings API" icon="tool" href="/en/docs/aigne-hub/api-reference-embeddings-32e774/"} Discover how to create numerical representations of text for machine learning tasks. --- ## Deployment Scenarios URL: https://www.arcblock.io/en/docs/aigne-hub/deployment-scenarios-32e774/ Choosing the right deployment model is crucial for aligning AIGNE Hub with your specific operational and business objectives. This document outlines the two primary deployment scenarios available, providing a clear comparison to guide your architectural decisions. Each mode is designed to address distinct use cases, from internal corporate use to public-facing commercial services. AIGNE Hub offers the flexibility to be deployed in one of two primary modes: as a self-hosted gateway for internal enterprise use or as a multi-tenant service provider platform with a built-in credit and billing system. The selected mode dictates the configuration for billing, user management, and security. ![Deployment Scenarios](https://media.arcblock.io/lib/a6/a620f1e3b9fe6c92.w1600.webp) The following sections provide an overview of each deployment scenario. For detailed configuration instructions, please refer to the specific sub-documents. ## Deployment Models AIGNE Hub supports two distinct operational modes, each tailored to different organizational needs. Below is a summary of each model and its intended use case. ::::card-group ::link-card{title="Enterprise Self-Hosting" description="Deploy AIGNE Hub within your own infrastructure as a centralized gateway for internal teams. This model provides maximum control over data and security, with billing handled directly between your organization and the upstream AI providers." icon="briefcase" href="/en/docs/aigne-hub/deployment-scenarios-enterprise-self-hosting-32e774/"} ::link-card{title="Service Provider Mode" description="Configure AIGNE Hub to function as a public-facing, monetized AI service. This mode enables a credit-based billing system, allowing you to set custom pricing, manage user subscriptions, and generate revenue from AI services." icon="shopping-bag" href="/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/"} :::: ## Summary This document has introduced the two primary deployment scenarios for AIGNE Hub. The Enterprise Self-Hosting model is ideal for internal use, prioritizing security and direct billing. In contrast, the Service Provider mode is designed for public-facing services that require multi-tenancy and monetization. For detailed implementation guides, please proceed to the relevant sections: - [Enterprise Self-Hosting](/en/docs/aigne-hub/deployment-scenarios-enterprise-self-hosting-32e774/) - [Service Provider Mode](/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/) --- ## Enterprise Self-Hosting URL: https://www.arcblock.io/en/docs/aigne-hub/deployment-scenarios-enterprise-self-hosting-32e774/ Deploying AIGNE Hub within your own infrastructure grants your organization complete control over AI model access, data privacy, and operational costs. This guide provides a structured approach to configuring and managing a self-hosted AIGNE Hub instance for secure, internal enterprise use. ## Overview The enterprise self-hosting model is designed for organizations that prioritize data security and direct management of their AI resources. By deploying AIGNE Hub within your own network perimeter, you create a centralized, secure gateway for all internal teams and applications to access a variety of AI models. This approach offers several distinct advantages: - Enhanced Security: All data, including prompts, responses, and API credentials, remains within your corporate network, ensuring compliance with strict data privacy policies. - Direct Billing: You maintain a direct billing relationship with each AI provider (e.g., OpenAI, Anthropic, Google). AIGNE Hub tracks usage, but all costs are paid directly to the vendors, simplifying budget allocation and eliminating third-party billing complexities. - Full Control: Your team has complete administrative control over the instance, including which models are available, who can access them, and how they are configured. - Internal Integration: Seamlessly connect AIGNE Hub with your existing internal authentication systems, such as your corporate OAuth provider, for unified and secure access management. This deployment scenario is ideal for development teams, corporate AI initiatives, and any application requiring robust, private access to generative AI capabilities. ## Architectural Considerations When deploying AIGNE Hub for internal enterprise use, it functions as a centralized gateway within your security perimeter. All internal applications and services route their AI requests through the Hub, which then securely communicates with the external AI providers. ![Enterprise Self-Hosting](https://media.arcblock.io/lib/0a/0a431417ad2ea78b.w1600.webp) ### Key Components - AIGNE Hub Instance: A dedicated Blocklet running on your internal infrastructure (e.g., a private cloud, on-premises server, or VPC). - Internal Applications: Your services, developer environments, and internal tools that need to consume AI services. - Authentication System: Your corporate identity provider (e.g., an internal OAuth 2.0 server) that manages user access. - External AI Providers: The upstream LLM and AIGC services that AIGNE Hub connects to. In this configuration, the Hub acts as the sole intermediary. Internal applications do not need direct access to provider API keys, which significantly strengthens your security posture. ## Configuration Steps Configuring AIGNE Hub for enterprise use is a straightforward process focused on connecting providers and securing access. ### 1. Initial Deployment First, ensure you have a running instance of AIGNE Hub. If you have not yet installed it, follow the deployment instructions in our [Getting Started](/en/docs/aigne-hub/getting-started-32e774/) guide. The primary method is to launch it from the Blocklet Store onto your Blocklet Server. ### 2. Provider Configuration The core of the self-hosted setup is configuring AIGNE Hub to use your organization's own API keys for each AI provider. This ensures that all usage is billed directly to your corporate accounts. 1. Navigate to the admin dashboard of your AIGNE Hub instance. 2. In the left-hand sidebar, go to Config > AI Providers. 3. Here, you will see a list of supported AI providers. Click + Add Provider or select an existing one to configure. 4. Enter your organization's API credentials for the selected provider. The system stores these credentials securely using encryption. 5. Enable the providers you wish to make available to your internal users. ![Provider Configuration](https://raw.githubusercontent.com/AIGNE-io/aigne-hub/main/blocklets/core/screenshots/6fff77ec3c1fbefb780b2b79c61a36f7.png) ### 3. User Access and Security For internal use, you can manage access through your existing identity infrastructure. #### Internal OAuth Integration AIGNE Hub supports standard OAuth 2.0 for secure, single sign-on (SSO) access. By integrating it with your internal identity provider, employees can use their corporate credentials to access the Hub and generate API tokens for their applications. This centralizes user management and access control. To configure this, you will need to provide the client ID, client secret, and relevant endpoints from your OAuth provider in the AIGNE Hub security settings. #### Direct API Access For services or automated workflows, administrators can generate long-lived API keys directly within AIGNE Hub. These keys can be assigned specific permissions and revoked at any time, providing a secure method for non-interactive access. ## Usage and Management With the self-hosted instance configured, internal teams can begin using the unified API endpoint for all their AI needs. ### Unified API Endpoint All requests to any configured AI model are sent to your AIGNE Hub instance's API endpoints. The Hub automatically routes the request to the appropriate upstream provider, using the securely stored credentials. For example, an application can switch from using OpenAI's `gpt-4` to Anthropic's `claude-3-opus` simply by changing the model name in the API call, without needing to manage different API keys or endpoints. ### Usage Analytics Even though billing is handled directly with providers, AIGNE Hub provides detailed analytics on usage and costs. - Navigate to the Usage Analytics section in the admin dashboard. - Monitor token consumption, image generation counts, and estimated costs per user, team, or application. - Use this data for internal chargebacks, budget tracking, and identifying high-consumption services. This allows you to maintain visibility over AI spending across the organization without the complexity of parsing individual provider invoices. ## Summary The enterprise self-hosting model provides a secure, controlled, and efficient way to deploy AIGNE Hub for internal use. By centralizing AI access, keeping data within your security perimeter, and maintaining direct billing relationships, you can build a robust AI infrastructure that meets strict corporate requirements. For more advanced configurations, such as setting up a monetized service for external customers, please refer to the [Service Provider Mode](/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/) documentation. You can also find detailed information on securing your instance in the [Security & Access](/en/docs/aigne-hub/features-security-32e774/) guide. --- ## Service Provider Mode URL: https://www.arcblock.io/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/ Ready to offer your own multi-tenant AI service? This guide details how to activate Service Provider Mode in AIGNE Hub. You will learn to enable the credit-based billing system, integrate the Payment Kit, and define custom pricing to create a monetized AI gateway for your users. Service Provider Mode transforms AIGNE Hub from an internal tool into a full-featured, customer-facing platform. It builds upon the core features by adding a comprehensive billing and monetization layer, allowing you to resell access to a wide range of AI models. This is ideal for SaaS platforms, agencies, and developers looking to offer AI capabilities as a service. For information on deploying AIGNE Hub for internal use, see the [Enterprise Self-Hosting](/en/docs/aigne-hub/deployment-scenarios-enterprise-self-hosting-32e774/) documentation. ## How It Works When Service Provider Mode is enabled, AIGNE Hub operates on a prepaid, credit-based system. The following diagram illustrates the workflow: ![Service Provider Mode](https://media.arcblock.io/lib/3e/3e4eeb130709f751.w1600.webp) The workflow is as follows: ::::steps :::step{title="User Onboarding"} New users are automatically registered within the system. You can configure starter credits to allow them to test the service immediately. ::: :::step{title="Credit Purchase"} Users purchase credits through a payment link. This process is managed by the Payment Kit, a companion Blocklet that handles checkout sessions and payment processing. ::: :::step{title="AI Model Usage"} Users make API calls to AIGNE Hub to interact with various AI models. ::: :::step{title="Credit Deduction"} For each API call, AIGNE Hub calculates the cost based on your custom-defined model rates and deducts the corresponding amount from the user's credit balance. ::: :::step{title="Usage Tracking"} All transactions are recorded, providing both the administrator and the user with detailed analytics on consumption and spending. ::: :::: This model provides a flexible and scalable way to manage a multi-tenant AI service, ensuring that usage is billed accurately and automatically. ![AIGNE Hub dashboard with a modal for adding a new model rate, showing fields for configuration.](https://media.arcblock.io/lib/46/467a43898fb97a96.w1600.webp) ## Configuration Steps Enabling the credit-based billing system involves installing the Payment Kit and configuring your pricing models. ### 1. Install the Payment Kit The Payment Kit is a separate Blocklet that integrates with AIGNE Hub to handle all payment-related functionalities, including customer management, credit purchasing, and checkout processes. To install it: 1. Navigate to the Blocklet Store in your Blocklet Server admin interface. 2. Search for "Payment Kit". 3. Click "Launch" and follow the installation wizard to deploy it. Once the Payment Kit is running, AIGNE Hub will automatically detect it and enable the necessary billing features. ### 2. Define Custom Pricing Models After enabling the billing system, you must define the rates at which user consumption will be charged. This allows you to set your own pricing, which can include a margin on top of the costs from the upstream AI providers. 1. In the AIGNE Hub admin dashboard, navigate to Config > Model Rates. 2. Click "Add Model Rate" to open the configuration modal. 3. Define the pricing for a specific model by filling in the required fields: 4. - Model Name: The identifier for the model (e.g., `gpt-4o`). - Rate Type: The type of content the model handles (e.g., Text, Image). - Providers: The upstream AI provider for this model. - Model Cost: The actual cost you pay to the provider. - AIGNE Hub Credit Rate: The price in credits you will charge your users. - Description: An optional description for the model rate. ![The Model Rates configuration page in AIGNE Hub, displaying a table of AI models and their associated pricing.](https://media.arcblock.io/lib/3c/3c965b1fec89be97.w1600.webp) By setting a higher credit rate than your actual cost, you can generate a profit margin on each transaction. You can create multiple pricing tiers for the same model or different rates for various customer groups if needed. ### 3. Configure the Credit Purchase Link To allow users to buy credits, you need to set up a payment link. The Payment Kit can automatically generate a default link, or you can create a custom one. 1. A default payment link is created automatically when the Payment Kit is installed. You can find and manage it within the Payment Kit's interface. 2. In the AIGNE Hub admin dashboard, go to Billing & Credits > Settings. 3. Enter the URL for your credit purchase page in the Credit Payment Link field. This link will be provided to users when their balance is low. This setup ensures a seamless experience for users to recharge their credit balance and continue using the service without interruption. ## Managing User Credits As an administrator, you have full control over user credit balances and can view detailed transaction histories. ### Viewing User Balances To see a user's current credit balance, pending deductions, and total credits purchased: 1. Navigate to the Users section in the AIGNE Hub admin dashboard. 2. Select a user from the list to view their details. 3. The user's credit information will be displayed, providing a complete overview of their account status. ### Reviewing Transactions AIGNE Hub logs every transaction that consumes credits. This includes API calls for chat completions, image generation, and other AI tasks. - Credit Grants: Records of all credits added to a user's account, either through purchase or manual grants. - Credit Transactions: A detailed log of all deductions, showing which AI model was used, the amount consumed, and the timestamp of the event. You can access these logs through the Billing & Credits section, allowing for transparent auditing and easy resolution of any billing inquiries. ## Summary By enabling Service Provider Mode, you can leverage AIGNE Hub's powerful multi-provider gateway to build and scale your own monetized AI service. The integration with the Payment Kit provides a robust, automated system for managing credit-based billing, custom pricing, and user consumption. For a deeper dive into monitoring consumption, refer to the [Usage & Cost Analytics](/en/docs/aigne-hub/features-analytics-32e774/) guide. To understand how to manage upstream providers, see [Provider Management](/en/docs/aigne-hub/features-provider-management-32e774/). --- ## Core Features URL: https://www.arcblock.io/en/docs/aigne-hub/features-32e774/ This section provides a technical deep-dive into the key functionalities of AIGNE Hub. By the end, you will understand the platform's primary capabilities, from unified AI model interactions and provider management to robust security and detailed analytics, forming a solid foundation for leveraging the system. AIGNE Hub is engineered to serve as a central gateway, streamlining all interactions with a diverse range of Large Language Models (LLMs) and AI services. It unifies API access, centralizes security, and provides comprehensive visibility into usage and costs. The platform's features are designed to support both internal enterprise deployments and multi-tenant service provider models. The following diagram provides a high-level overview of AIGNE Hub's architecture and its core components. ![Core Features](https://media.arcblock.io/lib/55/550ea91d14c6145c.w1600.webp) For more detailed information on specific features, please refer to the following sections: ::::card-group ::link-card{title="Provider Management" description="Learn how to connect, configure, and manage upstream AI providers." icon="cloud" href="/en/docs/aigne-hub/features-provider-management-32e774/"} ::link-card{title="Usage & Cost Analytics" description="Understand how to monitor system-wide and per-user consumption and costs." icon="bar-chart" href="/en/docs/aigne-hub/features-analytics-32e774/"} ::link-card{title="Security & Access" description="Review the security architecture, including access control and data protection." icon="shield-check" href="/en/docs/aigne-hub/features-security-32e774/"} :::: ## AI Service Unification AIGNE Hub abstracts the complexity of integrating with multiple AI providers by offering a single, consistent set of API endpoints. This allows developers to build applications without being locked into a specific vendor and to switch between models seamlessly. ### Core AI Capabilities The platform provides standardized access to the most common generative AI modalities: - 💬 Chat Completions: Engage with conversational AI and advanced text generation models for a wide range of applications. The system supports standard and streaming responses through an OpenAI-compatible API. - 🖼️ Image Generation: Access generative image models like DALL·E for AI-powered image creation and editing tasks. - 🧠 Embeddings: Generate vector representations of text for use cases such as semantic search, clustering, and retrieval-augmented generation (RAG). ### Built-in Model Playground AIGNE Hub includes an interactive playground for testing and experimenting with any connected AI model in real time. This tool is invaluable for prompt engineering, model comparison, and rapid prototyping without writing any code. ![AIGNE Hub's interactive playground for testing AI models.](https://media.arcblock.io/lib/84/84151b07ec025b9f.w1600.webp) ## Centralized Management and Analytics Effective management and operational visibility are central to the AIGNE Hub design. The platform provides a unified dashboard to control, monitor, and analyze all AI-related activities. ### Provider and Billing Configuration From a single administrative interface, you can manage all aspects of the service. - Provider Management: Connect to a growing list of AI providers, including OpenAI, Anthropic, Google Gemini, and Amazon Bedrock. Credentials are encrypted and stored securely. - Flexible Billing System: Operate in two primary modes. For internal use, you can connect your own provider keys and pay them directly. For public-facing services, you can enable the credit-based billing system, set custom pricing rates, and monetize your AI gateway. ![The AI provider configuration screen in AIGNE Hub.](https://media.arcblock.io/lib/75/759f20b4abfeccdf.w1600.webp) ### Usage and Cost Analytics The analytics dashboard offers deep insights into consumption and spending across all providers, models, and users. - Usage Tracking: Monitor key metrics such as token consumption, API requests, and latency in real time. - Cost Analysis: Track spending against your provider accounts or, in service provider mode, monitor revenue and credit consumption. This data is essential for budgeting, forecasting, and optimizing AI expenditures. ## Security and Access Control AIGNE Hub is built with enterprise-grade security to protect sensitive data and ensure controlled access to powerful AI models. - Encrypted Credential Storage: All upstream provider API keys and credentials are encrypted using AES-256 to prevent unauthorized access. - OAuth Integration: Secure access for applications and users through industry-standard OAuth 2.0 protocols. - API Key Management: Generate and manage API keys within AIGNE Hub, allowing for fine-grained control over application access. - Audit Logging: A comprehensive audit trail logs all significant events, including API requests, configuration changes, and user activity, ensuring accountability and compliance. ## Summary AIGNE Hub provides a comprehensive suite of features designed to unify, manage, and secure your organization's access to generative AI. By centralizing provider integrations, offering detailed analytics, and enforcing robust security measures, it serves as a critical infrastructure component for any team building with AI. To continue, explore the detailed documentation for each core feature area: - [Provider Management](/en/docs/aigne-hub/features-provider-management-32e774/): Dive into the specifics of connecting and configuring AI services. - [Usage & Cost Analytics](/en/docs/aigne-hub/features-analytics-32e774/): Learn how to leverage the analytics dashboard for operational insights. - [Security & Access](/en/docs/aigne-hub/features-security-32e774/): Understand the platform's security mechanisms in detail. --- ## Usage & Cost Analytics URL: https://www.arcblock.io/en/docs/aigne-hub/features-analytics-32e774/ Understanding AI model consumption is crucial for managing costs, monitoring performance, and ensuring fair resource allocation. This document provides a detailed guide on how to query usage statistics, track costs, and interpret the data models AIGNE Hub uses for analytics and reporting. ## Overview AIGNE Hub records every API interaction as a `ModelCall` entry. These records form the basis for all usage analytics. The system provides several API endpoints to query and aggregate this data, allowing you to monitor consumption for the entire system or on a per-user basis. This enables detailed tracking of token usage, credit consumption, and overall API call volume. ## Data Models Understanding the underlying data structures is essential for effectively querying and interpreting analytics data. The following diagram illustrates how a `ModelCall` record is generated and used by the analytics endpoints. ![Usage & Cost Analytics](https://media.arcblock.io/lib/28/28c803b95e528073.w1600.webp) ### The ModelCall Object Every request made to an AI provider through the hub is logged as a `ModelCall`. This object contains detailed information about the request, its execution, and the associated costs. - **id** `string` *(required)* — A unique identifier for the model call record. - **providerId** `string` *(required)* — The identifier of the AI provider used for the call. - **model** `string` *(required)* — The specific model that was called (e.g., 'gpt-4o-mini'). - **credentialId** `string` *(required)* — The ID of the credential used for authentication with the provider. - **type** `string` *(required)* — The type of the API call. Possible values include 'chatCompletion', 'embedding', 'imageGeneration', 'audioGeneration', 'video', or 'custom'. - **totalUsage** `number` *(required)* — A normalized usage metric. For text models, this is typically the total number of tokens (input + output). - **usageMetrics** `object` — A detailed breakdown of usage, such as input and output tokens. - **inputTokens** `number` — The number of tokens in the input prompt. - **outputTokens** `number` — The number of tokens in the generated response. - **credits** `number` *(required)* — The number of credits consumed by the call, based on the configured model rates. - **status** `string` *(required)* — The final status of the call. Can be 'success' or 'failed'. - **duration** `number` — The duration of the API call in seconds. - **errorReason** `string` — If the call failed, this field contains the reason for the failure. - **appDid** `string` — The DID of the application that initiated the call. - **userDid** `string` *(required)* — The DID of the user who made the call. - **requestId** `string` — An optional client-side request identifier for tracing. - **callTime** `number` *(required)* — The Unix timestamp when the call was made. - **createdAt** `string` *(required)* — The timestamp when the record was created in the database. ## Querying Usage Data You can retrieve analytics data through several REST API endpoints. These endpoints require authentication. ### Fetching Usage Statistics To get a summarized and aggregated view of usage over a specific period, use the `GET /api/user/usage-stats` endpoint. For system-wide analytics, administrators can use `GET /api/user/admin/user-stats`. Request Parameters - **startTime** `string` *(required)* — The start of the time range as a Unix timestamp. - **endTime** `string` *(required)* — The end of the time range as a Unix timestamp. - **allUsers** `boolean` — When using /api/user/model-calls, set to true to fetch data for all users. This is restricted to admin users. Example Request **Requesting user stats** ```bash curl -X GET 'https://your-aigne-hub-url/api/user/usage-stats?startTime=1672531200&endTime=1675228799' \ --header 'Authorization: Bearer ' ``` Response Body The endpoint returns a comprehensive object containing a summary, daily breakdowns, model statistics, and trend comparisons. - **summary** `object` — An object containing aggregated totals for the specified period. - **totalCredits** `number` — Total credits consumed. - **totalCalls** `number` — Total number of API calls. - **modelCount** `number` — Total number of unique models used. - **byType** `object` — An object with usage statistics broken down by call type (e.g., 'chatCompletion'). - **[callType]** `object` - **totalUsage** `number` — Total usage (e.g., tokens) for this type. - **totalCredits** `number` — Total credits consumed by this type. - **totalCalls** `number` — Total calls of this type. - **successCalls** `number` — Number of successful calls of this type. - **dailyStats** `array` — An array of objects, each representing a day's usage statistics. - **date** `string` — The date in 'YYYY-MM-DD' format. - **credits** `number` — Total credits consumed on this day. - **tokens** `number` — Total tokens processed on this day. - **requests** `number` — Total API calls made on this day. - **modelStats** `array` — An array listing the most frequently used models. - **providerId** `string` — The ID of the provider for the model. - **model** `string` — The name of the model. - **totalCalls** `number` — Total number of calls made to this model. - **trendComparison** `object` — Comparison of usage between the current and previous period. - **current** `object` — Statistics for the current period. - **previous** `object` — Statistics for the equivalent previous period. - **growth** `object` — Growth rates between the two periods. ### Listing Model Calls For a detailed, chronological log of individual API requests, use the `GET /api/user/model-calls` endpoint. This provides access to the raw `ModelCall` records with pagination and filtering. Request Parameters - **page** `number` (default: `1`) — The page number for pagination. - **pageSize** `number` (default: `50`) — The number of items to return per page. Maximum is 100. - **startTime** `string` — The start of the time range as a Unix timestamp. - **endTime** `string` — The end of the time range as a Unix timestamp. - **search** `string` — A search term to filter results by model name, application DID, or user DID. - **status** `string` — Filter by call status. Can be 'success', 'failed', or 'all'. - **model** `string` — Filter by a specific model name. - **providerId** `string` — Filter by a specific provider ID. - **appDid** `string` — Filter by a specific application DID. - **allUsers** `boolean` — If true, returns model calls for all users (admin only). Example Request **Listing model calls** ```bash curl -X GET 'https://your-aigne-hub-url/api/user/model-calls?page=1&pageSize=10&status=failed' \ --header 'Authorization: Bearer ' ``` Response Body The response is a paginated list of `ModelCall` objects. **response.json** ```json { "count": 1, "list": [ { "id": "z8VwXGf6k3qN...", "providerId": "openai", "model": "gpt-4o-mini", "credentialId": "z3tXy..._default", "type": "chatCompletion", "totalUsage": 150, "usageMetrics": { "inputTokens": 100, "outputTokens": 50 }, "credits": 0.0002, "status": "failed", "duration": 2, "errorReason": "API key is invalid.", "appDid": "z2qa9sD2tFAP...", "userDid": "z1...", "requestId": null, "callTime": 1675228799, "createdAt": "2023-01-31T23:59:59.000Z", "updatedAt": "2023-01-31T23:59:59.000Z", "traceId": null, "provider": { "id": "openai", "name": "openai", "displayName": "OpenAI", "baseUrl": "https://api.openai.com/v1", "region": null, "enabled": true }, "appInfo": { "appName": "My AI App", "appDid": "z2qa9sD2tFAP...", "appLogo": "...", "appUrl": "..." }, "userInfo": { "did": "z1...", "fullName": "John Doe", "email": "john.doe@example.com", "avatar": "..." } } ], "paging": { "page": 1, "pageSize": 10 } } ``` ### Exporting Model Calls You can export the model call history to a CSV file for offline analysis or reporting using the `GET /api/user/model-calls/export` endpoint. This endpoint accepts the same filtering parameters as the listing endpoint. Example Request **Exporting model calls** ```bash curl -X GET 'https://your-aigne-hub-url/api/user/model-calls/export?startTime=1672531200&endTime=1675228799' \ --header 'Authorization: Bearer ' \ -o model-calls-export.csv ``` The server will respond with a `text/csv` file containing the requested data. ## Summary The analytics features in AIGNE Hub provide powerful tools for monitoring and understanding AI model usage. By leveraging the `ModelCall` data model and the associated API endpoints, you can build dashboards, generate reports, and gain critical insights into your operational costs and performance. For details on how credits are configured and billed, refer to the [Service Provider Mode](/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/) documentation. --- ## Provider Management URL: https://www.arcblock.io/en/docs/aigne-hub/features-provider-management-32e774/ Effective management of upstream AI providers is crucial for maintaining a reliable and cost-efficient AI gateway. AIGNE Hub centralizes this process, offering a unified interface to connect, configure, and manage credentials for various AI services. This section details the procedures for handling provider settings, credentials, and model rates. The following diagram illustrates how Providers, Credentials, and Model Rates are interconnected within AIGNE Hub: ![Provider Management](https://media.arcblock.io/lib/9b/9bcb86d95ae0edb9.w1600.webp) ## Provider Configuration Providers are the foundational elements that connect AIGNE Hub to upstream AI services like OpenAI, Google, and AWS Bedrock. Proper configuration ensures that the hub can route requests to the appropriate service. ![Provider Configuration UI showing a list of configured AI providers like OpenAI, Google, and AWS Bedrock.](https://media.arcblock.io/lib/75/759f20b4abfeccdf.w1600.webp) ### Add a Provider To integrate a new AI service, you must add it as a provider. Each provider requires a unique name, a display name for the UI, and service-specific details like a `baseUrl` or `region`. #### Request Body - **name** `string` *(required)* — The official name of the provider. Must be one of the supported provider values (e.g., openai, google, bedrock). - **displayName** `string` *(required)* — A user-friendly name for the provider that will be displayed in the UI. - **baseUrl** `string` — The base URL for the provider's API endpoint. This is required for most providers but is optional for AWS Bedrock. - **region** `string` — The AWS region for the Bedrock service. This is required only for the bedrock provider. - **enabled** `boolean` (default: `true`) — Enables or disables the provider. A disabled provider will not be used for routing requests. ### Update a Provider You can modify an existing provider's configuration, such as its `baseUrl`, `region`, or `enabled` status. #### Request Body - **baseUrl** `string` — The updated base URL for the provider's API endpoint. - **region** `string` — The updated AWS region for the Bedrock service. - **enabled** `boolean` — The new status for the provider. ### List and Delete Providers You can retrieve a list of all configured providers or delete a specific provider by its ID. Deleting a provider will also remove all associated credentials and model rates. ## Credential Management Credentials are used to authenticate with the upstream AI providers. AIGNE Hub encrypts and securely stores these credentials, associating them with a specific provider. Each provider can have multiple credentials, which allows for key rotation and load balancing. ### Add a Credential When adding a credential, you must specify its type and value. AIGNE Hub automatically validates the credential against the provider's service to ensure it is active. #### Request Body - **name** `string` *(required)* — A descriptive name for the credential (e.g., "Team A API Key"). - **credentialType** `string` (default: `api_key`) — The type of credential. Supported values are api_key and access_key_pair. - **value** `string or object` *(required)* — The credential value. For api_key, this is a string. For access_key_pair, this is an object containing access_key_id and secret_access_key. ### Credential Validation AIGNE Hub includes an endpoint to check the validity of a stored credential. This action triggers a test connection to the provider using the specified credential to confirm it is active and has the necessary permissions. ### Update and Delete Credentials Existing credentials can be updated with new values or deleted. When a credential is deleted, it is permanently removed from the system and can no longer be used for requests. ## Model Rate Management Model rates define the cost of using specific AI models in AIGNE Hub credits. These rates are essential for systems operating in [Service Provider Mode](/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/) where usage is billed based on credits. ![Model Rate Configuration UI showing a list of AI models with their associated costs.](https://media.arcblock.io/lib/3c/3c965b1fec89be97.w1600.webp) ### Add a Model Rate You can define rates for any model supported by a configured provider. This includes setting separate credit costs for input and output tokens (for text models) or per image/video (for generation models). #### Request Body - **model** `string` *(required)* — The identifier for the model (e.g., gpt-4o-mini). - **type** `string` *(required)* — The type of service. Supported values are chatCompletion, imageGeneration, embedding, and video. - **providers** `array` *(required)* — An array of provider IDs to which this model rate applies. This allows a single model to be offered by multiple providers. - **inputRate** `number` *(required)* — The cost in credits for input (e.g., per 1,000 tokens). - **outputRate** `number` *(required)* — The cost in credits for output (e.g., per 1,000 tokens). - **unitCosts** `object` — The actual cost from the provider in USD per million units (tokens/images). Used for automatic rate calculation based on profit margins. - **input** `number` *(required)* — The input cost per million units. - **output** `number` *(required)* — The output cost per million units. - **modelMetadata** `object` — Additional metadata about the model's capabilities. - **maxTokens** `number` — The maximum context window size. - **features** `array` — An array of supported features, such as `tools` or `vision`. ### Bulk Update Model Rates To simplify pricing adjustments, AIGNE Hub supports bulk updates of model rates based on a defined profit margin and credit price. The system automatically recalculates the `inputRate` and `outputRate` for all models that have `unitCosts` defined. The calculation is as follows: `New Rate = (Unit Cost * (1 + Profit Margin / 100)) / Credit Price` #### Request Body - **profitMargin** `number` *(required)* — The desired profit margin as a percentage (e.g., 20 for 20%). - **creditPrice** `number` *(required)* — The price of a single credit in USD. ### Update and Delete Model Rates Individual model rates can be modified or removed. If a model rate is deleted, the corresponding model will no longer be available for users if credit-based billing is enabled. ## Summary This section covered the core functionalities for managing AI providers, credentials, and model rates within AIGNE Hub. Proper configuration of these resources is essential for the security, reliability, and financial management of your AI services. For more information on related topics, refer to the following sections: ::link-card{title="Service Provider Mode" icon="briefcase" href="/en/docs/aigne-hub/deployment-scenarios-service-provider-32e774/"} Learn how to configure credit-based billing and custom pricing models. ::link-card{title="Security and Access Control" icon="shield" href="/en/docs/aigne-hub/features-security-32e774/"} Understand the security architecture, including encrypted storage and access controls. --- ## Security & Access URL: https://www.arcblock.io/en/docs/aigne-hub/features-security-32e774/ A secure and well-managed system is critical for any enterprise-grade deployment. This section details the robust security architecture of AIGNE Hub, covering authentication, credential management, access control, and logging to ensure the integrity and confidentiality of your AI operations. The following diagram provides a high-level overview of the security layers and components within AIGNE Hub: ![Security & Access](https://media.arcblock.io/lib/6e/6eb62829c76d1117.w1600.webp) ## Authentication AIGNE Hub integrates with Blocklet Server's standard authentication mechanisms, providing a secure and unified login experience. The primary method of authentication is through DID Connect, which leverages decentralized identity for passwordless and secure access. ### DID Connect Integration All user authentication is handled by the underlying Blocklet Server environment. When a user logs into AIGNE Hub, they are authenticated via the DID Connect wallet authenticator, ensuring that access is tied to a verified decentralized identity. This approach eliminates the need for traditional username/password combinations, reducing the risk of credential theft. The system uses an authentication storage database (`auth.db`) to manage session tokens securely. For details on how to authenticate programmatic API requests to AIGNE Hub, please see the [API Authentication](/en/docs/aigne-hub/api-reference-authentication-32e774/) documentation. ## Encrypted Credential Storage Storing API keys and other sensitive credentials from upstream AI providers is a critical security concern. AIGNE Hub addresses this by implementing strong, field-level encryption for all sensitive credential data. ### Encryption Mechanism When you add a provider's credentials (like an API key or a secret access key), the sensitive parts of the credential are encrypted before being stored in the database. - Encryption Target: Only sensitive fields are encrypted. For example, in an `access_key_pair`, the `secret_access_key` is encrypted, while the `access_key_id` remains in plaintext for identification purposes. Standalone `api_key` values are always encrypted. - Technology: Encryption and decryption operations are handled by the `@blocklet/sdk/lib/security` module, which provides robust cryptographic functions. The following code snippet from the `AiCredential` model illustrates the process: **ai-credential.ts** ```typescript // Encrypt credential value (only encrypts sensitive fields) static encryptCredentialValue(credential: CredentialValue): CredentialValue { const encrypted: CredentialValue = { ...credential }; // Encrypt sensitive fields if (credential.secret_access_key) { encrypted.secret_access_key = security.encrypt(credential.secret_access_key); } if (credential.api_key) { encrypted.api_key = security.encrypt(credential.api_key); } // access_key_id remains plaintext return encrypted; } // Decrypt credential value static decryptCredentialValue(encryptedCredential: CredentialValue): CredentialValue { const decrypted: CredentialValue = { ...encryptedCredential }; // Decrypt sensitive fields if (encryptedCredential.secret_access_key) { decrypted.secret_access_key = security.decrypt(encryptedCredential.secret_access_key); } if (encryptedCredential.api_key) { decrypted.api_key = security.decrypt(encryptedCredential.api_key); } return decrypted; } ``` ### Credential Masking To prevent accidental exposure of sensitive keys in the user interface, AIGNE Hub automatically masks credential values. Only the first four and last four characters of a key are displayed, with the rest replaced by asterisks. ## Role-Based Access Control (RBAC) AIGNE Hub employs a simple yet effective Role-Based Access Control (RBAC) model to restrict access to administrative functions. The roles are inherited from the Blocklet Server environment. ### Available Roles | Role | Permissions | |---|---| | `owner` | Full administrative access to the AIGNE Hub instance. Can manage providers, configure billing, view analytics, and manage all settings. | | `admin` | Same permissions as the `owner`. This role is also considered a privileged user with full access to administrative functions. | | `guest` | Standard user role. Can use the AI services provided by the Hub (e.g., Playground, API access) but cannot access the admin configuration. | Access to critical administrative API endpoints is protected by a middleware that verifies the user's role, ensuring that only users with `owner` or `admin` roles can perform management tasks. **security.ts** ```typescript import { auth } from '@blocklet/sdk/lib/middlewares'; // Middleware to ensure the user has 'owner' or 'admin' role export const ensureAdmin = auth({ roles: ['owner', 'admin'] }); ``` ## Audit Logging Comprehensive audit logging is essential for security analysis, troubleshooting, and compliance. AIGNE Hub maintains detailed logs of all significant activities within the system. ### Logged Activities - API Requests: All incoming requests to the AI endpoints are logged, including the user, model requested, and usage metrics. - Administrative Actions: Actions performed in the admin panel, such as adding or updating a provider, changing model rates, or modifying configurations, are recorded. - Credential Management: Events related to the creation, modification, or deletion of provider credentials. These logs provide a complete history of usage and administrative changes, which is invaluable for security audits and operational monitoring. ## Summary AIGNE Hub is designed with a multi-layered security model to protect your AI gateway. By combining DID-based authentication, strong encryption for credentials, role-based access control, and detailed audit logs, it provides a secure foundation for both internal enterprise use and public-facing services. For more information on related features, please refer to the following sections: ::::card-group ::link-card{title="Provider Management" description="Learn how to connect and configure upstream AI providers." icon="server" href="/en/docs/aigne-hub/features-provider-management-32e774/"} ::link-card{title="Usage & Cost Analytics" description="Explore how to monitor system-wide and per-user consumption." icon="pie-chart" href="/en/docs/aigne-hub/features-analytics-32e774/"} :::: --- ## Getting Started URL: https://www.arcblock.io/en/docs/aigne-hub/getting-started-32e774/ This guide provides a direct, task-oriented path to deploying and operating AIGNE Hub. By following these steps, a functional instance can be configured in under 30 minutes, enabling immediate integration with upstream AI providers and downstream applications. The following diagram illustrates the core workflow for getting started: ![Getting Started](https://media.arcblock.io/lib/d3/d3e59dfe0b305a8f.w1600.webp) ## Prerequisites Before proceeding, ensure the following requirements are met: - Blocklet Server: A running instance of Blocklet Server is required to host AIGNE Hub. - AI Provider Accounts: You must have active accounts and corresponding API keys for the AI services you intend to connect (e.g., OpenAI, Anthropic, Google Gemini). ## Step 1: Install AIGNE Hub AIGNE Hub is distributed as a Blocklet, ensuring a standardized and straightforward installation process. 1. Navigate to the Blocklet Store within your Blocklet Server instance. 2. Use the search bar to find "AIGNE Hub". 3. Click the "Launch" button on the AIGNE Hub blocklet page. 4. Follow the on-screen installation wizard to complete the deployment. The system will handle the necessary setup and configuration automatically. After the installation is complete, AIGNE Hub will be running and accessible from your Blocklet Server dashboard. ![AIGNE Hub Dashboard](https://media.arcblock.io/lib/a9/a9cd09be56bd2502.w1600.webp) ## Step 2: Connect AI Providers Once installed, the next step is to connect AIGNE Hub to your chosen AI providers. All credentials are AES-encrypted at rest to ensure security. 1. Access the AIGNE Hub admin dashboard. 2. Navigate to the configuration section via the sidebar: Config → AI Providers. 3. Click the "+ Add Provider" button to open the configuration modal. 4. Select the desired provider from the list (e.g., OpenAI, Google Gemini). 5. Enter your API key and any other required credentials or parameters. 6. Save the configuration. The provider will now appear in the list with a "Connected" status if the credentials are valid. Repeat this process for all the AI providers you wish to manage through AIGNE Hub. ![Configure AI Providers](https://media.arcblock.io/lib/75/759f20b4abfeccdf.w1600.webp) ## Step 3: Choose an Operational Mode AIGNE Hub can be configured for two primary deployment scenarios. Your choice determines the next steps for usage and integration. ### For Internal Enterprise Use This is the default and simplest mode, designed for teams that need a centralized AI gateway for internal applications. - Direct Billing: Your organization is billed directly by the AI providers (OpenAI, Anthropic, etc.). AIGNE Hub tracks usage for analytics but does not handle payments. - Secure Access: Integrate with your existing OAuth provider for secure, single-sign-on access for internal developers and applications. With providers configured, your AIGNE Hub instance is ready for immediate use. Proceed to the [Basic Usage](#basic-usage) section. ### For Use as a Service Provider This mode turns AIGNE Hub into a multi-tenant, monetized service by enabling the credit-based billing system. - Monetization: Charge end-users for AI usage on a credit basis. You set the pricing per model, creating a margin over the costs from the upstream provider. - Payment Kit Integration: This mode requires installing the Payment Kit blocklet, which handles credit purchases, invoicing, and payment processing. - User Onboarding: Automatically grant new users a starting balance of credits to encourage adoption. To enable this mode, navigate to Preferences, enable credit-based billing, and configure your model pricing rates. ![Configure Model Rates](https://media.arcblock.io/lib/3c/3c965b1fec89be97.w1600.webp) ## Step 4: Basic Usage After configuration, you can begin making API requests through AIGNE Hub's unified endpoint or test models directly in the built-in Playground. ### Using the Playground The Playground provides a no-code interface for interacting with any connected AI model. It is an excellent tool for testing, prompt engineering, and demonstrations. 1. Navigate to the Playground section in the AIGNE Hub dashboard. 2. Select a connected model from the dropdown menu. 3. Enter your prompt and submit to receive a response. ![AIGNE Hub Playground](https://media.arcblock.io/lib/84/84151b07ec025b9f.w1600.webp) ### Programmatic Usage Integrate AIGNE Hub into your applications by making API calls to its OpenAI-compatible endpoints. The following example shows how to use the `@aigne/aigne-hub` client library. **AIGNEHubChatModel.ts** ```typescript // Using AIGNE Framework with AIGNE Hub import { AIGNEHubChatModel } from "@aigne/aigne-hub"; const model = new AIGNEHubChatModel({ baseURL: "https://your-aigne-hub-url", apiKey: "your-oauth-access-key", // Use an access key generated via OAuth model: "aignehub/gpt-3.5-turbo", // Prefix model with 'aignehub/' }); const result = await model.invoke({ messages: "Hello, AIGNE Hub!", }); console.log(result); ``` This code snippet initializes a chat model client pointing to your self-hosted AIGNE Hub instance. It authenticates using an OAuth access key and makes a request to the `gpt-3.5-turbo` model through the gateway. ## Summary You have now successfully deployed, configured, and tested your AIGNE Hub instance. The gateway is operational and ready to serve AI capabilities to your teams and applications. For more advanced configurations and a deeper dive into the platform's features, refer to the following documentation: ::::card-group ::link-card{title="Deployment Scenarios" description="Explore detailed architectures for enterprise self-hosting and public service provider modes." icon="server" href="/en/docs/aigne-hub/deployment-scenarios-32e774/"} ::link-card{title="API Reference" description="Review the technical specifications for the Chat Completions, Image Generation, and Embeddings endpoints." icon="code" href="/en/docs/aigne-hub/api-reference-32e774/"} :::: --- ## Overview URL: https://www.arcblock.io/en/docs/aigne-hub/overview-32e774/ Struggling to manage a growing collection of API keys, billing systems, and integrations for different AI providers? This document provides a comprehensive introduction to AIGNE Hub, a unified AI gateway that simplifies this complexity. You will learn about its core capabilities, key benefits, and system architecture, establishing a clear understanding of its value for infrastructure management. AIGNE Hub serves as a centralized gateway, enabling you to connect your applications to leading Large Language Models (LLMs) and AIGC services through a single, consistent API. It streamlines the management of API keys, usage tracking, and security, whether you're deploying it as an internal tool or as a monetized, multi-tenant service. ## Why AIGNE Hub? Integrating multiple AI services into an organization's infrastructure introduces significant operational overhead. Teams often face a fragmented landscape of provider-specific APIs, disparate billing cycles, and inconsistent security models. This complexity slows down development, complicates cost management, and increases the security surface area. The diagram below illustrates how AIGNE Hub sits between your applications and various AI providers to solve these challenges: ![Overview](https://media.arcblock.io/lib/cd/cda398893dea7b57.w1600.webp) AIGNE Hub is designed to solve these specific challenges by providing: - A Single Point of Integration: It offers a unified, OpenAI-compatible API endpoint for all connected providers. This eliminates the need for developers to learn and maintain multiple SDKs and integration patterns. - Centralized Credential Management: All upstream API keys are stored securely in one place with AES encryption, reducing the risk of key exposure across various applications and environments. - Unified Usage and Cost Analytics: Gain full visibility into consumption and spending across all models, users, and providers from a single dashboard. This simplifies budget tracking and resource allocation. - Flexible Deployment Models: AIGNE Hub can be deployed for purely internal use, where you bring your own keys, or as a public-facing service with a built-in, credit-based billing system. ## Core Capabilities AIGNE Hub provides a robust set of features designed to streamline the entire lifecycle of AI service consumption and management. ::::card-group ::link-card{title="Multi-Provider Management" description="Connect to over 8 leading AI providers like OpenAI, Anthropic, and Google Gemini through a single interface." icon="cloud"} ::link-card{title="Unified API Endpoints" description="Interact with all models using OpenAI-compatible RESTful APIs for chat completions, image generation, and embeddings." icon="zap"} ::link-card{title="Usage & Cost Analytics" description="Monitor token usage, cost, and latency metrics across all users and providers with a comprehensive analytics dashboard." icon="chart"} ::link-card{title="Centralized Security" description="Benefit from encrypted API key storage, OAuth integration, role-based access control (RBAC), and detailed audit logs." icon="shield-check"} ::link-card{title="Flexible Billing System" description="Optionally enable a credit-based billing system powered by Payment Kit to monetize your service for external users." icon="credit-card"} ::link-card{title="Built-in Playground" description="Test and experiment with any connected AI model in real-time directly from the AIGNE Hub user interface." icon="activity"} :::: ## Supported AI Providers AIGNE Hub supports a growing list of major AI providers. The system is designed to be extensible, with new providers being added continuously. | Provider | Supported Services | |---|---| | OpenAI | GPT models, DALL-E, Embeddings | | Anthropic | Claude models | | Google Gemini | Gemini Pro, Vision models | | Amazon Bedrock | AWS-hosted foundation models | | DeepSeek | Advanced reasoning models | | xAI | Grok models | | OpenRouter | Aggregator for multiple providers | | Ollama | Local model deployment | | Doubao | Doubao AI models | | Poe | Poe AI platform | ## System Architecture AIGNE Hub is engineered for reliability and performance, built as a [Blocklet](https://blocklet.io) on the AIGNE framework. This architecture ensures seamless integration within the AIGNE ecosystem and provides a robust foundation for cloud-native deployment and scaling. The primary components of the stack include: - Backend: Built with Node.js and TypeScript, providing a strongly-typed and efficient server-side environment. - Frontend: A modern user interface constructed with React 19. - Database: Utilizes SQLite with the Sequelize ORM for local data storage, ensuring simple setup and reliable data management. - Framework: Leverages the latest version of the AIGNE Framework for core functionality and integration capabilities. ![AIGNE Hub Dashboard](https://raw.githubusercontent.com/AIGNE-io/aigne-hub/main/blocklets/core/screenshots/fc46e9461382f0be7541af17ef13f632.png) ## Summary This overview has introduced AIGNE Hub as a unified AI gateway designed to simplify infrastructure management for multi-provider AI services. We have outlined the problems it solves, its core features, and its technical architecture. For the next steps, you can proceed to the following sections for more detailed information: ::::card-group ::link-card{title="Getting Started" description="Follow a step-by-step guide to deploy and configure your AIGNE Hub instance in under 30 minutes." icon="rocket" href="/en/docs/aigne-hub/getting-started-32e774/"} ::link-card{title="Deployment Scenarios" description="Explore the architectural guidance for deploying AIGNE Hub for internal enterprise use or as a monetized service." icon="flag" href="/en/docs/aigne-hub/deployment-scenarios-32e774/"} :::: --- ## Release Notes URL: https://www.arcblock.io/en/docs/aigne-hub/release-notes-32e774/ This document provides a detailed record of all notable changes, new features, and bug fixes for AIGNE Hub. DevOps and SRE teams can use this information to track the platform's evolution, understand the impact of each update, and schedule upgrades accordingly. ## October 2025 ### New Features - Video Generation Support: The platform's core capabilities have been extended to support video generation models. A new `video` type has been added to the `ModelCalls` table to track these requests. - Media Duration Analytics: To enhance usage tracking for multimedia content, a `mediaDuration` field has been added to the `Usages` table. This allows for more precise cost and consumption analysis of audio and video generation. - Request Tracing: A `traceId` field has been added to all model calls. This identifier improves observability by allowing requests to be tracked consistently across different system components, simplifying debugging and performance analysis. ## September 2025 ### New Features - Credential Weighting for Load Balancing: A `weight` attribute has been added to AI provider credentials. This feature enables weighted load balancing, allowing administrators to distribute API traffic across multiple keys based on predefined priorities, such as routing more requests to higher-limit or lower-cost credentials. - Credential Error Tracking: An `error` field has been added to the `AiCredentials` table. This allows the system to store the last known error associated with a specific credential, improving diagnostics and making it easier to identify and resolve issues with provider API keys. ## August 2025 ### New Features - Model Health Monitoring: A new system for tracking the operational status of individual AI models has been introduced. The `AiModelStatuses` table now records the health and availability of each model, providing better insight into provider-side issues and improving overall system reliability. This summary provides an overview of recent updates. For more detailed information on integrating and managing these features, please refer to the relevant sections of the documentation. --- ## AIGNE Studio URL: https://www.arcblock.io/en/docs/aigne-studio/ --- ## Introduce URL: https://www.arcblock.io/en/docs/aigne-studio/ai-studio/ ## Overview AI Studio is an AI application development platform based on the Blocklet ecosystem, which can help you: - No code/low code rapid development AI applications - Prompt Version Control - Automated testing prompt - Fast Release: Easily publish AI applications based on the Blocklet ecosystem - Collaborative Editing: Team members can collaborate on editing the development prompt You can also learn more about AI Studio through the following link: --- ## Guide URL: https://www.arcblock.io/en/docs/aigne-studio/getting-started-z1f81/ ## Overview In this guide, you can learn how to start AI Studio and begin using it. - [Start AI Studio](/en/docs/aigne-studio/launch/) --- ## Start AI Studio URL: https://www.arcblock.io/en/docs/aigne-studio/launch/ Before you start, you need to install the DID wallet, you can refer to [https://support.didwallet.io/howToDownload](https://support.didwallet.io/howToDownload) to complete the wallet download and installation. ## Launch AI Studio. First time using the Blocklet platform? You can directly click the "Launch" button from the [AI Studio](https://store.blocklet.dev/blocklets/z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB) in the Blocklet Store, and run an AI Studio instance in our Serverless. If you have already run your own Blocklet application, you can also install the AI Studio component by adding components. [AI Studio](https://store.blocklet.dev/blocklets/z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB) Want to run Blocklet Server by yourself? You can refer to: [Welcome](/en/docs/blocklet-developer/welcome/) --- ## AIGNE WebSmith URL: https://www.arcblock.io/en/docs/aigne-web-smith/ --- ## Advanced Features URL: https://www.arcblock.io/en/docs/aigne-web-smith/advanced-features-c47353/ Once you have mastered the basics of generating and updating your website, you can explore the advanced features of AIGNE WebSmith to gain more granular control and add unique, powerful visual elements. This section covers how to manage your component library and leverage specialized components for more dynamic and engaging pages. This section provides an overview of advanced capabilities. For detailed instructions, please refer to the specific sub-documents: ::::card-group ::link-card{title="Use Custom Component Libraries" description="Learn how to pull and update the component library that WebSmith uses to construct your website's visual elements." icon="book-open" href="/en/docs/aigne-web-smith/advanced-features-use-custom-component-libraries-c47353/"} ::link-card{title="Use Special Components" description="Discover how to implement powerful, pre-built components like the Terminal Player to create visually rich web pages." icon="box" href="/en/docs/aigne-web-smith/advanced-features-use-special-components-c47353/"} :::: ## Summary This section serves as a gateway to the more powerful and customizable aspects of AIGNE WebSmith. By learning to manage component libraries and utilize special components, you can significantly enhance the visual appeal and functionality of your generated website. For a complete list of all available commands and their parameters, consult the [Command Reference](/en/docs/aigne-web-smith/reference-command-c47353/). --- ## Use Custom Component Libraries URL: https://www.arcblock.io/en/docs/aigne-web-smith/advanced-features-use-custom-component-libraries-c47353/ Websites generated by AIGNE WebSmith are constructed from a library of pre-designed visual elements called components. While WebSmith includes a standard set of components, you can define and manage a custom component library using a Pages Kit project. This allows for tailored designs and functionalities specific to your needs. This section explains how to use the `component pull` command to synchronize your local component library with the one defined in your Pages Kit project. ## Overview of the Component Library A custom component library is a collection of standardized, reusable page elements tailored for your project. When you generate a website, WebSmith will use your custom components to build the pages, ensuring brand consistency and unique layouts. Keeping your local library synchronized is important for two main reasons: ::::steps :::step{title="Access to New Designs"} As new visual components are designed and added to your Pages Kit project, pulling them into your local library makes them available for the AI to use. ::: :::step{title="Bug Fixes and Improvements"} Updates may contain improvements or fixes to existing components, enhancing the quality and appearance of your website. ::: :::: ## Syncing Your Custom Library The `aigne web component pull` command fetches the latest version of the component library from a specific URL provided by your Pages Kit project. ### Command Syntax To pull the latest components, use the following command structure: **Component Pull** ```bash aigne web component pull --url ``` You can also use the alias `comp`: **Component Pull (Alias)** ```bash aigne web comp pull --url ``` ### Parameters - **--url** `string` *(required)* — The unique URL for pulling components from your Pages Kit project. This URL contains the necessary project ID and security credentials. You can typically find this URL within your project's settings page in Pages Kit. ### The Update Process Updating your component library is a straightforward but important process. Follow these steps carefully. #### Step 1: Run the Pull Command Execute the command with the specific URL provided by your Pages Kit project. **Component Pull** ```bash aigne web component pull --url "https://your-pages-kit/api/projects/your-project-id/components/pull?secret=your-secret&hash=your-hash" ``` The tool will connect to the URL and download the latest component library definition. #### Step 2: Review the Changes After a successful download, WebSmith will display a summary of the changes. It will show a comparison between your existing library and the new one, detailing the number of "atomic" (basic) and "composite" (complex) components. An example of the output might look like this: ``` ✅ Pull Components successfully (not saved yet)! 📊 New Components Statistics: 🔹 Atomic components: 10 (9 → 10) • LogoV1 - A component to display a heading and a list of logos... • RichText - A RichText component primarily displays the title... • NewFeatureCard - A brand new card for features... 🧩 Composite components: 22 (22 → 22) • Logo Wall - Structure - Optional section title... • User Review - Structure (top → bottom) - Review Content/Quote... ``` This summary allows you to verify the incoming changes before they are applied. #### Step 3: Confirm the Update WebSmith will then prompt you for confirmation before making any permanent changes to your local files. ``` Do you want to update (save) the built-in components file? (y/N) ``` - Press `y` and `Enter` to proceed with the update. - Press `n` or `Enter` to cancel the operation. No changes will be made. #### Step 4: Re-generate Your Website If you confirm the update, WebSmith will perform two critical actions: ::::steps :::step{title="Save the New Library"} It overwrites your local `builtin-component-library.yaml` file with the new version. ::: :::step{title="Clear Generated Content"} To ensure your website is rebuilt correctly with the new components, it will delete all previously generated page files from your workspace and output directories. ::: :::: Once the process is complete, you will see a confirmation message and a reminder for the next step. ``` 💾 New components saved. 🧹 Cleaned previous generated content. 🚀 Next: please run below command to re-generate pages: `aigne web generate` ``` You must now run the `generate` command to create your website pages using the updated component library. ## Summary The `component pull` command is the standard procedure for keeping your local environment's visual building blocks in sync with your custom Pages Kit repository. The process involves pulling the latest library, reviewing the changes, confirming the update, and finally, re-generating your website to apply the new components. For more information on creating pages, proceed to the [Create Website](/en/docs/aigne-web-smith/guides-create-website-c47353/) section. --- ## Use Special Components URL: https://www.arcblock.io/en/docs/aigne-web-smith/advanced-features-use-special-components-c47353/ AIGNE WebSmith includes a library of special components designed to add powerful visual and interactive elements to your website with minimal configuration. These pre-built components handle complex functionalities, allowing you to create engaging user experiences efficiently. This section provides an overview of the available special components and directs you to detailed guides for implementing them. By leveraging these tools, you can significantly enhance the presentation and interactivity of your web pages. ## Available Components WebSmith offers several advanced components out of the box. The primary components are detailed below. For specific implementation instructions, please refer to the linked sub-pages. ::::card-group ::link-card{title="Terminal Player" description="A component for embedding animated terminal session recordings directly into your web pages. It is ideal for tutorials, command-line tool demonstrations, and technical documentation." icon="terminal" href="/en/docs/aigne-web-smith/advanced-features-use-special-components-terminal-player-c47353/"} ::link-card{title="Latest Updates" description="A component to showcase recent changes, news, or blog posts on your website." icon="file-text" href="/en/docs/aigne-web-smith/advanced-features-use-special-components-latest-updates-c47353/"} :::: ## Summary Using special components can dramatically improve the visual appeal and functional capabilities of your website. For detailed instructions on how to use these components, refer to their respective documentation sections. - [Terminal Player](/en/docs/aigne-web-smith/advanced-features-use-special-components-terminal-player-c47353/) - [Latest Updates](/en/docs/aigne-web-smith/advanced-features-use-special-components-latest-updates-c47353/) --- ## Latest Updates URL: https://www.arcblock.io/en/docs/aigne-web-smith/advanced-features-use-special-components-latest-updates-c47353/ The 'Latest Updates' component provides a dynamic way to showcase recent news, blog posts, or announcements on your website. It integrates with Discuss Kit, a blog system, to automatically fetch and display content, keeping your site fresh and demonstrating ongoing activity. This component is particularly useful for: - Showcasing new features, updates, or technical articles. - Providing "Proof & Momentum"—visible, ongoing progress. - Reinforcing brand transparency and engagement. ## How to Use To implement the 'Latest Updates' section, you must prepare a data source file and then reference it in your website's generation rules. The process is straightforward and ensures that the AI can correctly locate and render the content. ### Step 1: Prepare the Data File First, create a YAML file that acts as a data descriptor, telling WebSmith where to fetch the blog content from. A recommended location for this file is `src/blog-list-data.yaml`. #### Example Data File **src/blog-list-data.yaml** ```yaml blogTitle: "Latest Updates" blogDescription: "Get the latest updates right here." blogUrl: "https://www.arcblock.io" # Or your Discuss Kit Blocklet URL blogLabel: "did-domain" blogMoreButtonText: "See More" ``` #### Field Descriptions | Field | Description | Required | |---|---|---| | `blogTitle` | The main title displayed for the section. It is recommended to keep this under 60 characters for clarity. | Yes | | `blogDescription` | A brief summary that appears under the title, explaining the content of the section. | Yes | | `blogUrl` | The source URL, usually your Discuss Kit Blocklet. WebSmith automatically extracts titles, summaries, cover images, and dates. The Discuss Kit API must be publicly accessible. | Yes | | `blogLabel` | An optional filter tag to display content from a specific category. The value should be obtained from your Discuss Kit site (e.g., the `labels` query parameter in the URL). | No | | `blogMoreButtonText` | The text for an optional "See More" button that can link to your main blog or news page. | No | ### Step 2: Register the Data Source After creating the data file, you must register it so WebSmith can find and use it. Add the file path to the `sourcesPath` field in your `config.yaml`: **config.yaml** ```yaml sourcesPath: - src/blog-list-data.yaml ``` If you are updating an existing site, you must also add the file path to `.aigne/web-smith/pages/workspace/website-structure.yaml` under the `sourceIds` section. This ensures WebSmith can locate the new data source during `update` operations. **.aigne/web-smith/pages/workspace/website-structure.yaml** ```yaml sourceIds: - src/blog-list-data.yaml ``` ### Step 3: Define the Section in Generation Rules Next, instruct the AI on how to use the data source by adding a rule to your WebSmith `config.yaml` file. The rule should specify the section's position, component type, and data source. #### Example Rule **config.yaml** ```yaml rule: Section 2 must render the `Latest Updates` section using `src/blog-list-data.yaml` as immediate proof and momentum. ``` This example rule accomplishes the following: - Positioning: Places the 'Latest Updates' component as the second section on the page. - Component Type: Identifies the section as a "Latest Updates" or "Blog List" type. - Data Source: Points to `src/blog-list-data.yaml` as the source of configuration. Alternatively, when using the `update` command, you can provide a direct prompt instead of editing the `config.yaml` file: ``` Change section 2 to “Latest Updates” and generate its content using src/blog-list-data.yaml. ``` ### Step 4: Generate or Update Your Website With the data file and generation rule in place, run the appropriate command to have AIGNE WebSmith build or refresh your site. If generating for the first time, use `aigne web generate`. To add a section to an existing site, use `aigne web update` and select the document to add the section. WebSmith will now automatically load your YAML data, retrieve the latest posts from the specified Discuss Kit URL, and render the 'Latest Updates' section on your website. ## Summary The 'Latest Updates' component is a powerful tool for keeping your website content current and engaging. By following the simple steps of creating a data file and defining a generation rule, you can automate the process of displaying news and blog posts directly on your site. For more information on other special components, please refer to the documentation on [Using Special Components](/en/docs/aigne-web-smith/advanced-features-use-special-components-c47353/). --- ## Terminal Player URL: https://www.arcblock.io/en/docs/aigne-web-smith/advanced-features-use-special-components-terminal-player-c47353/ The Terminal Player is a specialized component used to display interactive, pre-recorded terminal sessions on your website. This component is an effective tool for demonstrating command-line instructions, showcasing software installations, or guiding users through technical processes in a clear and replayable format. This component utilizes recordings created in the `asciinema` format, which ensures a lightweight, text-based capture of the terminal output. ## Overview of the Process The workflow for using the Terminal Player can be broken down into a sequence of clear, manageable steps. The process begins with the developer recording a terminal session and concludes with the end-user viewing the interactive playback on the website. The following diagram illustrates this process: ![Terminal Player](https://media.arcblock.io/lib/be/be2df1d1543db676.w1600.webp) ## Creating a Terminal Recording To use the Terminal Player, you must first create a recording file. The recommended tool for this is `asciinema`, an open-source command-line utility for recording and sharing terminal sessions. ### Step 1: Install the asciinema CLI First, install the `asciinema` tool on your local machine. The installation method varies depending on your operating system. **Installation** ```bash # On macOS using Homebrew brew install asciinema # On Ubuntu/Debian using APT sudo apt install asciinema # Using pipx (cross-platform) pipx install asciinema ``` For additional installation options, please refer to the official [asciinema documentation](https://docs.asciinema.org/). ### Step 2: Record Your Session Once `asciinema` is installed, you can begin recording a terminal session by executing the `rec` command. **Recording Command** ```bash # Start a new recording, which will be saved to 'my-demo.cast' asciinema rec my-demo.cast ``` After initiating the command, perform all the actions you wish to capture within your terminal. To stop the recording, press `Ctrl+D` or type the `exit` command. A file named `my-demo.cast` will be saved in your current directory. You can verify the playback locally by running `asciinema play my-demo.cast`. Important Considerations: - Plan your steps: The recording captures all actions, including pauses and errors. It is advisable to prepare a script beforehand. - Terminal Dimensions: The player will replicate the column and row dimensions of the terminal used for recording. Ensure your terminal window is sized appropriately to prevent content wrapping or truncation during playback. ### Step 3: Convert the .cast File to JSON The Terminal Player component requires the recording data to be in a specific JSON format. An online converter is available to simplify this conversion process. ::::steps :::step{title="Navigate to the Converter:"} Open the [ArcBlock Terminal Player Converter](https://arcblock.github.io/ux/?path=/story/data-display-terminal-player--recording-guide) in your web browser. ::: :::step{title="Upload Your File:"} Drag and drop your `.cast` file onto the page. ::: :::step{title="Preview and Download:"} The tool will generate a live preview of your recording. After confirming it is correct, download the converted `.json` file. ::: :::step{title="Add to Project:"} Place the downloaded JSON file into your website's media or assets directory. ::: :::: ## Using the Recording Once the JSON recording file is placed in your project's media or assets directory, it becomes available to the AI. There is no need to manually configure the component in a YAML file. Simply describe the need for a terminal demonstration in your content source files. When you run `aigne web generate` or `aigne web update`, the AI will automatically find the relevant `.json` recording and use the Terminal Player component to display it on your website. **AIGNE CLI Commands** ```bash # To generate the website from scratch aigne web generate # To update the website with your changes aigne web update ``` For additional information on recording, you may consult the official [asciinema website](https://asciinema.org/). ## Additional Resources - [ArcBlock Terminal Player Converter](https://arcblock.github.io/ux/?path=/story/data-display-terminal-player--recording-guide) - [asciinema Documentation](https://docs.asciinema.org/) --- ## Getting Started URL: https://www.arcblock.io/en/docs/aigne-web-smith/getting-started-c47353/ Use this guide as the fastest path to a working site: install the AIGNE CLI, gather source materials, run `aigne web generate`, approve the plan, and review the generated pages—all in one place. ## See the end-to-end flow ![Getting Started](https://media.arcblock.io/lib/76/76cf186f467012cd.w1600.webp) ## Prerequisites - Node.js 20 or newer (npm is included). Check with `node -v`. - AIGNE account (optional). You can use the hosted models that ship with the AIGNE CLI without adding API keys. - Source material that describes your product or service. For a deeper checklist, read the [Prepare Materials](/en/docs/aigne-web-smith/reference-prepare-materials-c47353/) guide. ## Step 1. Install and verify the AIGNE CLI Install the AIGNE CLI globally so the `aigne` command is available from any folder: **Install AIGNE CLI** ```bash npm install -g @aigne/cli ``` Verify that installation succeeded: **--help** ```bash aigne web --help ``` Need the beta channel? Install with `npm install -g @aigne/cli@beta` and run `aigne web upgrade --beta` to pick up the latest agents. ## Step 2. Create a project workspace Set up a clean directory for your first site and switch into it: **Create workspace** ```bash mkdir my-first-websmith-site cd my-first-websmith-site ``` Copy or create the documents, briefs, and media you want the AI to read inside this folder (or a nearby `sources` directory). Well-defined materials dramatically improve output quality, so spend a few minutes following the [preparation checklist](/en/docs/aigne-web-smith/reference-prepare-materials-c47353/). ## Step 3. Run aigne web generate From the project directory, start the generator: **Generate website** ```bash aigne web generate ``` Because this is a new workspace, WebSmith launches an interactive wizard that captures: ::::steps :::step{title="Website purpose"} - e.g., SaaS marketing site, documentation hub, investor update. ::: :::step{title="Target audiences"} - developers, customers, investors, etc., so tone and proof match the reader. ::: :::step{title="Website scale"} - choose minimal, standard, comprehensive, or let the AI decide. ::: :::step{title="Languages"} - pick the primary locale and any translations to produce. ::: :::step{title="Pages directory"} - where generated files are stored (defaults to `aigne/web-smith/pages`). ::: :::step{title="Source paths"} - directories or files that contain your product knowledge. ::: :::step{title="Custom rules"} - constraints such as tone, terminology, or compliance reminders. ::: :::: Your answers are written to `.aigne/doc-smith/config.yaml` so future runs can reuse them. ## Step 4. Review the configuration Open the generated config and sanity-check the values, especially `sourcesPath`. Below is a trimmed example: **config.yaml** ```yaml projectName: My Awesome Project projectDesc: This is a project that does amazing things. pagePurpose: - saas targetAudienceTypes: - developers websiteScale: standard locale: en pagesDir: aigne/web-smith/pages sourcesPath: - ./docs - ./briefs/product-overview.md - ./evidence rules: > Use confident, concrete copy. Highlight 99.99% uptime and SOC 2 compliance. ``` > Important: `sourcesPath` controls everything the AI can reference. Point it to the exact directories that contain your briefs, specs, pricing sheets, and proof so the generated copy is accurate. > ## Step 5. Approve the plan and inspect pages After reading your config, WebSmith proposes a site map (pages, sections, and key talking points). Approve it to let the AI draft content and assemble the Astro/React templates. When the run finishes you will see: - Generated files inside the `pagesDir` you selected. - Logs for each page that show which source files were used. - Suggestions for next actions (publish, translate, or iterate). Open the generated pages locally or continue straight to the [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/) guide to push them live. ## What's next? ::::card-group ::link-card{title="Prepare Materials" description="Build a repeatable content kit so every generation starts with high-quality inputs." icon="folder" href="/en/docs/aigne-web-smith/reference-prepare-materials-c47353/"} ::link-card{title="Create Website" description="Dive deeper into advanced options for the `generate` workflow." icon="wrench" href="/en/docs/aigne-web-smith/guides-create-website-c47353/"} ::link-card{title="Publish Website" description="Turn the generated pages into a live site on WebSmith Cloud or your own infra." icon="rocket" href="/en/docs/aigne-web-smith/guides-publish-website-c47353/"} :::: --- ## Guides URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-c47353/ Need to manage your website day-to-day? This section provides step-by-step guides for common operations like creating your site, publishing updates, managing translations, and customizing the look and feel. Follow these tutorials to keep your website running smoothly. ::::card-group ::link-card{title="Create Website" description="Breaks down the create workflow, including configuration fields, prompts, and ways to validate the output before publishing." icon="plus" href="/en/docs/aigne-web-smith/guides-create-website-c47353/"} ::link-card{title="Update Website" description="Learn how to use the 'update' command to make changes or provide feedback to refine the content on your existing pages." icon="edit" href="/en/docs/aigne-web-smith/guides-update-website-c47353/"} ::link-card{title="Publish Website" description="Explains every publish target, from WebSmith Cloud to fully custom infrastructure, with prerequisites and validation tips." icon="upload" href="/en/docs/aigne-web-smith/guides-publish-website-c47353/"} ::link-card{title="Localize Website" description="Explains how to use the 'translate' command to automatically create different language versions of your website pages." icon="globe" href="/en/docs/aigne-web-smith/guides-localize-website-c47353/"} ::link-card{title="Customize Theme" description="Covers how to use the 'theme' command to generate and apply different visual styles and color schemes to your website." icon="palette" href="/en/docs/aigne-web-smith/guides-customize-theme-c47353/"} ::link-card{title="Manage Preferences" description="Explains how to use the 'prefs' command to view, manage, and clear saved user preferences to customize WebSmith's behavior." icon="settings" href="/en/docs/aigne-web-smith/guides-manage-preferences-c47353/"} ::link-card{title="Cleanup Workspace" description="Shows you how to use the 'clear' command to safely remove generated files, workspace data, or the entire configuration." icon="trash" href="/en/docs/aigne-web-smith/guides-cleanup-workspace-c47353/"} ::link-card{title="Interactive Mode (Beta)" description="Use the interactive mode as a conversational co-pilot to iteratively plan, edit, and polish your site." icon="bot" href="/en/docs/aigne-web-smith/guides-interactive-mode-c47353/"} :::: ## Summary These guides cover the essential commands for managing your website's lifecycle. For more advanced topics and a complete command listing, please refer to the [Advanced Features](/en/docs/aigne-web-smith/advanced-features-c47353/) and [Reference](/en/docs/aigne-web-smith/reference-c47353/) sections. --- ## Cleanup Workspace URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-cleanup-workspace-c47353/ Use this guide to run `aigne web clear` safely, whether you want to wipe generated pages, reset cached data, or remove authorization tokens before handing off a project. The `clear` command is a utility for managing your project's workspace (typically the `./.websmith/tmp` directory). It allows you to selectively remove generated files, cached data, and configuration settings. This is particularly useful when you want to start a fresh build, reset your configuration, or remove sensitive authorization data. Executing the command can be a destructive action. Please ensure you have backed up any important data before proceeding. ## Interactive Clearing The simplest way to use the command is to run it without any arguments. This will launch an interactive prompt where you can select the specific items you wish to clear. **Cleanup Workspace** ```bash aigne web clear ``` This will present a list of available items to remove. You can navigate with the arrow keys, select items with the spacebar, and confirm your selection by pressing Enter. ## Clearable Targets The following table details the specific items that can be cleared, what they contain, and the command to clear them directly. | Target Name | Command Flag | Description | |---|---|---| | Website Structure | `websiteStructure` | Removes the website structure file (`website-structure.yaml`) from the workspace. Your original source content is not affected. | | Generated Pages | `generatedPages` | Deletes all generated page content from the workspace. This leaves the website structure file intact. | | Website Configuration | `websiteConfig` | Deletes the main `config.yaml` file. Caution: This action is irreversible. You will need to run `aigne web init` to generate a new configuration file. | | Authorizations | `authTokens` | Deletes the `.env.websmith` file, which stores authentication tokens. After clearing, you will need to re-authorize for operations like publishing. | | Deployment Config | `deploymentConfig` | Removes only the `appUrl` key from your `config.yaml` file. This is useful for resetting your deployment target without deleting the entire website configuration. | | Media File Descriptions | `mediaDescription` | Deletes the cached, AI-generated descriptions for your media assets. These will be automatically regenerated on the next run of the `generate` command. | | Translation Caches | `translationCaches` | Deletes the AI-generated translation caches. These will be regenerated automatically on the next publish. | ## Non-Interactive Clearing To bypass the interactive prompt, you can use the `--targets` flag followed by one or more target names. This is useful for scripting or automating cleanup tasks. ### Clearing a Single Target To clear a single item, specify its name with the `--targets` flag. **Clear Website Structure** ```bash aigne web clear --targets websiteStructure ``` ### Clearing Multiple Targets You can provide a space-separated list of targets to clear multiple items at once. The following example clears both the website structure and the generated pages. **Clear --targets Websitestructure Generatedpages** ```bash aigne web clear --targets websiteStructure generatedPages ``` ## Summary The `clear` command provides a safe and controlled way to manage your project's generated assets and configuration. Use the interactive mode for guided cleanup or the `--targets` flag for direct, automated control. Always exercise caution, especially when clearing the `websiteConfig`, to avoid unintended data loss. After clearing your workspace or generated pages, you may want to create the website again. For more details, see [Create Website](/en/docs/aigne-web-smith/guides-create-website-c47353/). --- ## Create Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-create-website-c47353/ Use this guide to turn your source material into a live-ready site with a single command. You will inspect the available `aigne web generate` flags, approve the AI-generated sitemap, and understand where the finished pages land on disk. If you need a quick reference to every flag and alias, run `aigne web -h`; the sample output below is what you should see. ![Output of aigne web -h, showing available flags and aliases](https://media.arcblock.io/lib/5c/5c43d2c28254dc14.w1600.webp) ## Creation Workflow The `aigne web generate` command initiates the entire website creation process. It reads your configuration, analyzes your source materials, plans the website's structure, generates content for each page, and assembles the final files. ### Usage To run the generation process, execute the following command in your terminal: **Create Website** ```bash aigne web generate ``` You can also use the aliases `gen` or `g`: **Create Website** ```bash aigne web gen ``` ### What Happens During Generate When you run the `generate` command, WebSmith performs the following sequence of operations: ::::steps :::step{title="Load Configuration"} It first looks for and loads the `config.yaml` file to understand your high-level requirements. If this file doesn't exist, it will automatically initiate a guided setup to create one. ::: :::step{title="Analyze Sources"} The AI scans the documents, markdown files, and other materials specified in the `sourcesPath` of your configuration to understand the subject matter. ::: :::step{title="Plan Website Structure"} Based on the purpose, audience, and source content, the AI proposes a logical sitemap for your website, outlining all the pages and their hierarchy. You will be prompted to review and approve this structure before content generation begins. ::: :::: ![Reviewing the proposed site structure before approving generation](https://media.arcblock.io/lib/2d/2df83fe441708a5a.w1600.webp) ::::steps :::step{title="Generate Page Content"} For each page in the approved structure, the AI generates detailed content, including titles, descriptions, and sections composed of professional components like hero banners, feature lists, and FAQs. ::: :::step{title="Save Website Files"} The final, structured content for each page is saved as YAML files in the directory specified by `pagesDir` in your configuration. These files are now ready for publishing. ::: :::: ![Generation run summary showing successful output and next steps](https://media.arcblock.io/lib/a0/a0f6b275e9ffe714.w1600.webp) ### Parameters The `generate` command accepts several optional parameters to customize its behavior. - **glossary** `string` — Specifies the path to a glossary file (e.g., @glossary.md). This ensures that project-specific terms are used consistently throughout the generated content. - **forceRegenerate** `boolean` — If set to true, the command will regenerate all pages from scratch, overwriting any previously generated files. This is useful after making significant changes to the config.yaml file or your source documents. Example with parameters: **Regenerate Website** ```bash # Regenerate the entire website using a glossary file aigne web generate --forceRegenerate --glossary "@glossary.md" ``` ## The Configuration File (config.yaml) The `config.yaml` file is the blueprint for your website. It provides the AI with the necessary context and constraints to build a site that meets your specific needs. This file defines the project, the site's purpose and audience, language settings, and file locations. Below is a detailed breakdown of the key properties within the `config.yaml` file. ### Configuration Options - **projectName** `string` *(required)* — The name of your project or website. This is used for metadata and publishing. - **projectDesc** `string` — A brief description of your project. - **projectLogo** `string` — A URL or local path to your project's logo. - **pagePurpose** `array` *(required)* — An array of strings defining the website's primary goals. Examples: landingPage, ecommerce, portfolio, corporate, blog, saas, nonprofit, education, mixedPurpose. - **targetAudienceTypes** `array` *(required)* — An array of strings identifying the primary audience. Examples: customers, businessOwners, marketers, designers, developers, investors, jobSeekers, students, generalPublic. - **websiteScale** `string` *(required)* — Defines the desired size and complexity of the website. Options include singlePage, minimal, standard, comprehensive, and aiDecide. - **rules** `string` — A field for any custom rules or specific instructions for the AI to follow during generation, such as tone of voice, content to exclude, or specific points to emphasize. - **locale** `string` *(required)* (default: `en`) — The primary language for the website content, specified by a language code (e.g., en, zh, es). - **translateLanguages** `array` — A list of language codes to translate the website into. For example, ['zh', 'fr']. - **pagesDir** `string` *(required)* — The local directory path where the generated website page files will be saved. - **sourcesPath** `array` *(required)* — An array of file paths or glob patterns that point to your source content. The AI will analyze these files to generate the website. ### Example config.yaml Here is an example of a complete `config.yaml` file with comments explaining each section. **config.yaml** ```yaml # Project information for page publishing projectName: AIGNE WebSmith projectDesc: AI-driven website generation tool projectLogo: https://www.aigne.io/image-bin/uploads/bc5afab4e6d282cc7f4aa444e9b9f7f4.svg projectId: aigne-websmith-docs projectSlug: aigne-websmith # ============================================================================= # Website Configuration # ============================================================================= # Purpose: What's the main outcome you want readers to achieve? # Available options (uncomment and modify as needed): # landingPage - Landing page / Homepage: Convert visitors into users or customers # ecommerce - E-commerce / Online store: Sell products or services online # portfolio - Portfolio / Showcase: Display creative work, projects, or achievements # corporate - Corporate / Business: Professional business website with company information # blog - Blog / Content site: Share articles, news, and regular content updates # saas - SaaS / Software product: Promote and onboard users to software services # nonprofit - Non-profit / Community: Promote causes, accept donations, engage volunteers # education - Educational / Learning: Provide courses, tutorials, or educational content # mixedPurpose - Multi-purpose website: Comprehensive website covering multiple needs pagePurpose: - saas # Target Audience: Who will be reading this most often? # Available options (uncomment and modify as needed): # customers - Customers / End users: People who buy or use your products/services # businessOwners - Business owners / Entrepreneurs: People running businesses looking for solutions # marketers - Marketing teams: People promoting products or managing campaigns # designers - Designers / Creative professionals: People focused on visual design and user experience # developers - Developers / Technical users: People building or integrating technical solutions # investors - Investors / Stakeholders: People evaluating business potential and growth # jobSeekers - Job seekers / Potential employees: People looking for career opportunities # students - Students / Learners: People seeking educational content or resources # generalPublic - General public / Mixed audience: Broad audience with varied interests and backgrounds targetAudienceTypes: - developers # Website Scale: How many pages should your website have? # Available options (uncomment and modify as needed): # singlePage - Single Page (only 1 page): All content consolidated into 1 page # minimal - Minimal (2-6 pages): Core pages only - quick to launch # standard - Standard (7-12 pages): Complete website with main sections [RECOMMENDED] # comprehensive - Comprehensive (12+ pages): Full-featured website with detailed sections # aiDecide - Let AI decide: Analyze project complexity and suggest appropriate scale websiteScale: standard # Custom Rules: Define specific page generation rules and requirements rules: 'Maintain a formal and technical tone. Avoid marketing jargon. Focus on practical, step-by-step instructions.' # Glossary: Define project-specific terms and definitions # glossary: "@glossary.md" # Path to markdown file containing glossary definitions locale: en # translateLanguages: # List of languages to translate the pages to # - zh # Example: Chinese translation # - en # Example: English translation pagesDir: ./aigne-web-smith/pages # Directory to save generated pages sourcesPath: # Source code paths to analyze - ./docs/**/*.md - ./README.md defaultDatasources: # Default datasources included in every page - ./media.md # minImageWidth: Only images wider than this value (in pixels) will be used in page generation media: minImageWidth: 800 ``` ## Summary By combining the `generate` command with a well-defined `config.yaml` file, you can efficiently produce a complete website tailored to your exact specifications. This process automates the heavy lifting of site structure and content creation, allowing you to focus on providing high-quality source material. After generating your website, the next step is to make it available online. Further reading: - [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/) --- ## Customize Theme URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-customize-theme-c47353/ Consistent colors, typography, and spacing make your site feel professional. This guide walks through the exact commands to generate a new WebSmith theme with AI assistance and then apply it to your live site. AIGNE WebSmith streamlines theme management with two sub-commands: - `theme generate` – capture your design direction and save it as a YAML theme file. - `theme apply` – upload any saved theme to your live site. Follow the steps below to create and apply a theme end to end. ## Generating a New Theme 1. Start the generator **Run command** ```bash aigne web theme generate ``` Alias: `aigne web theme gen` 2. Describe the look and feel The terminal asks for a name, palette, typography, and mood. Provide concrete cues (“dark background, neon accents, rounded headings”) so the AI can shape the design. 3. Review the preview list After generation, the theme appears in the local `themes` directory with metadata (primary color, fonts) as shown below. Edit the YAML if you want to fine‑tune tokens. ![Theme generation prompt showing the list of saved themes with metadata](https://media.arcblock.io/lib/81/8141d94b0cb8a9e1.w1600.webp) ## Applying a Theme After generating one or more themes, the `theme apply` command allows you to select a saved theme and apply it to your website. This command reads your local theme files, presents them as a list, and, upon your confirmation, uploads the selected theme to your site, making the changes live. ### Process ::::steps :::step{title="Run the Command"} Execute `aigne web theme apply` in your terminal. ::: :::step{title="Select a Theme"} The tool scans the `themes` directory and displays a list of all available themes you have generated. The list includes details like the theme name, primary color, and fonts to help you choose. ::: :::step{title="Review and Confirm"} The system will display the target website URL, the currently active theme, and the new theme you have selected. You will be asked for a final confirmation before any changes are made. ::: :::step{title="Apply to Website"} Once confirmed, the theme is uploaded and applied to your website. A success message will indicate that the process is complete. ::: :::: ### Usage To apply an existing theme, use the command below. ```sh aigne web theme apply ``` You can also specify the website URL directly as a parameter. If omitted, the `appUrl` from your `config.yaml` file will be used. ```sh aigne web theme apply --appUrl https://your-website.com ``` ### Parameters The `apply` command accepts the following parameters: - **appUrl** `string` — The full URL of your website. If you do not provide this, the command will use the appUrl defined in your config.yaml configuration file. - **config** `string` — The location of your configuration file. Defaults to the standard config.yaml path. ### Handling a Locked Theme To protect a website's live theme from accidental changes, Blocklet applications include a "theme lock" feature. If a theme is locked, any attempt to apply a new one from the terminal will be blocked. When you try to apply a theme to a locked site, you will encounter a `403 Forbidden` error: ``` Failed to apply theme: Failed to upload theme data: 403 Forbidden {"code":"internal_server_error","error":"Theme is locked and cannot be modified"} ``` To resolve this, you must unlock the theme through the website's administrative interface: 1. Log in to your website's administrative dashboard. 2. Navigate to WebSite > Theming in the admin menu. 3. Click the unlock button to remove the theme lock. 4. Run `aigne web theme apply` again. ![Unlock Theme Button Interface](https://media.arcblock.io/lib/a7/a7ca31b2bbce4b99.w1600.webp) By following these steps, you can effectively manage your website's visual identity. For the next step after updating your theme, you may want to review how to [publish your website](/en/docs/aigne-web-smith/guides-publish-website-c47353/). --- ## Interactive Mode(Beta) URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-interactive-mode-c47353/ > Note: Interactive mode is currently in beta. While fully functional, you may encounter unexpected behavior. We appreciate your feedback as we continue to improve this experience. > Use this guide to launch `aigne web chat`, speak to WebSmith in natural language, and let the assistant trigger generate/update/publish actions on your behalf. The `chat` command provides an interactive, conversational interface for building and managing your website. Instead of running individual commands like `generate` or `update`, you can describe your needs in plain language, and the AI assistant will guide you through the process. This is an ideal starting point for users who prefer a more guided experience. ## How It Works Interactive mode is powered by a dedicated AI agent that understands your requests and can use other WebSmith tools to perform tasks. It maintains a memory of your conversation, allowing you to make sequential changes and build on previous actions. The general workflow follows a simple, conversational loop, as illustrated in the diagram below: ![Interactive Mode(Beta)](https://media.arcblock.io/lib/d3/d3f8fc5f2fa1c2f0.w1600.webp) ## Starting an Interactive Session To begin, run the `chat` command from your terminal: **Command** ```bash aigne web ``` This will launch the assistant, which will greet you and wait for your instructions. ## What You Can Do The chat assistant can perform most of the core tasks available in the AIGNE WebSmith CLI. You can simply ask it to: - Generate a new website: Describe your website requirements, target audience, and desired style. - Update existing content: Specify which page or section you want to change and provide the new details. - Translate pages: Request translation of specific pages into another language. - Publish your site: Tell the assistant you're ready to publish your website to Pages Kit. - Manage files: Ask to see the current file structure or content of a specific page. ## Example Conversation Here is an example of how you might use interactive mode to create, modify, and publish a simple website. **Command Line** ```bash aigne web > Welcome to the AIGNE WebSmith interactive assistant! > How can I help you build your website today? You: I need to create a website for a new SaaS product that helps teams manage their projects. > Of course. Could you please provide a few more details? > - What are the core features of the product? > - Who is the target audience? > - What style should the website have (e.g., business, modern, playful)? You: The main features are task tracking, team collaboration, and reporting. The target audience is small to medium-sized business owners. Let's go with a modern business style. > Thank you. I have enough information to plan the website structure. > I will now generate the following pages: > - Home > - Features > - Pricing > - About Us > - Contact > ... > [Generation process starts] > ... > Website generation is complete. The files have been saved to the 'output' directory. > What would you like to do next? You: On the homepage, add a section for customer testimonials. > Understood. I will add a customer testimonials section to the homepage. > [Update process starts] > ... > The homepage has been updated. Is there anything else? You: No, that's all for now. Please publish the website. > I will now publish the website to your configured Pages Kit project. > [Publishing process starts] > ... > Your website has been successfully published. > You can now exit the chat by typing 'exit'. You: exit > Goodbye! ``` ## Exit Interactive Mode To end your session at any time, type `exit` or `quit` and press Enter. Interactive mode is a powerful way to manage your entire website lifecycle without needing to memorize specific commands and parameters. For more direct control, you can always use the standard commands detailed in the following sections. ### Further Reading - [Create Website](/en/docs/aigne-web-smith/guides-create-website-c47353/) - [Update Website](/en/docs/aigne-web-smith/guides-update-website-c47353/) - [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/) --- ## Localize Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-localize-website-c47353/ Use this guide to run `aigne web translate`, select the pages and languages you want, and save localized versions that are ready to publish alongside your primary site. AIGNE WebSmith provides a powerful and straightforward way to automatically translate your website content into multiple languages, enabling you to reach a global audience with minimal effort. The `translate` command uses AI to generate high-quality translations for your existing pages. This document will guide you through the process of translating your content, from basic interactive usage to more advanced options using command-line parameters. ## How Translation Works The translation process is designed to be simple and efficient. When you run the `translate` command, WebSmith performs the following steps: ::::steps :::step{title="Identifies Source Content"} It loads your existing website structure and content, determining the primary language from your configuration. ::: :::step{title="Selects Pages"} You can specify which pages to translate. If you don't, it will present an interactive list of all available pages for you to choose from. ::: :::step{title="Chooses Target Languages"} You can provide a list of target languages. If you don't, it will display a list of supported languages for you to select. ::: :::step{title="Generates Translations"} The AI processes the content of each selected page and generates a translated version for every chosen language. It can use an optional glossary to ensure consistent terminology. ::: :::step{title="Saves Translated Files"} The newly translated pages are saved into language-specific directories, ready for you to review and publish. ::: :::: ## Basic Usage For the most straightforward approach, you can run the command without any parameters. WebSmith will guide you through the process with interactive prompts. Run the following command in your terminal: **Localize Website** ```bash aigne web translate ``` ![Interactive prompt showing multiple languages selected for translation](https://media.arcblock.io/lib/0a/0a11eced20ec5faa.w1600.webp) You will be prompted to: 1. Select the pages you wish to translate (use the spacebar to select and enter to confirm). 2. Select the target languages from a list of supported options. Once you've made your selections, the AI will begin the translation process. ## Command Parameters For more control and for use in automated scripts, you can use the following command-line parameters. - **--pages** `array` — An array of page paths to translate. If omitted, you will be prompted to select pages interactively. For example: --pages /about /contact - **--langs** `array` — An array of language codes to translate to. If omitted, you will be prompted to select languages interactively. See the table below for a full list of supported languages. - **--glossary** `string` — A glossary of specific terms to ensure consistent terminology during translation. You can provide a string of key-value pairs or reference a file path using the @ prefix (e.g., @./glossary.txt). - **--feedback** `string` — Provide feedback to the AI to refine and improve existing translations. This is useful for making corrections or adjusting the tone. ## Examples ### Translate Specific Pages into Multiple Languages This command translates the `/about-us` and `/services/main` pages into Japanese and French without interactive prompts. **Translate Specific Pages** ```bash aigne web translate --pages /about-us /services/main --langs ja fr ``` ### Using a Glossary for Consistent Terminology To ensure that your brand name "WebSmith" and the term "SaaS" are translated consistently into Spanish, you can use the `--glossary` parameter. **Translate With Glossary** ```bash aigne web translate --langs es --glossary "WebSmith:WebSmith AI,SaaS:Software como Servicio" ``` For a larger glossary, it is more practical to use a file. Create a file named `glossary.txt` with your terms, and then reference it. **Translate With Glossary File** ```bash aigne web translate --langs de --glossary @./glossary.txt ``` ## Supported Languages The following table lists all languages currently available for translation. | Language | Code | |---|---| | English | `en` | | Chinese (Simplified) | `zh` | | Chinese (Traditional) | `zh-TW` | | Japanese | `ja` | | French | `fr` | | German | `de` | | Spanish | `es` | | Italian | `it` | | Russian | `ru` | | Korean | `ko` | | Portuguese | `pt` | | Arabic | `ar` | After translating your content, the next logical step is to make it available to your users. Learn how to deploy your multilingual site in the [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/) section. --- ## Manage Preferences URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-manage-preferences-c47353/ Use this guide to configure `aigne web prefs`, including how to list saved rules, toggle them on or off, and remove entries you no longer need. AIGNE WebSmith learns from your feedback to refine how it generates and updates your website. These learned instructions are stored as user preferences. The `prefs` command provides a way to view, manage, and clear these saved preferences, giving you full control over the AI's behavior. Managing your preferences ensures that the AI consistently adheres to your specific style guides, content requirements, and structural conventions over time. ## Listing Preferences To view all your currently saved preferences, use the `list` command. This command displays a table of all preference rules, including their ID, active status, scope, and the rule itself. **List Preferences** ```bash aigne web prefs list ``` You can also use the alias `ls`: **List Preferences** ```bash aigne web prefs ls ``` ### Example Output The output will be a formatted table, making it easy to review your saved rules. | ID | Active | Scope | Rule | |---|---|---|---| | pref_a1b2c3d4 | true | page | Write in a formal, professional tone. | | pref_e5f6g7h8 | true | structure | Do not generate pages or sections for outdated 'Legacy API Reference'. | | pref_i9j0k1l2 | false | theme | Healthcare websites must use warm color tones. | ## Toggling a Preference If you want to temporarily disable a preference without permanently deleting it, you can use the `toggle` command. This command switches the `active` status of a rule. To toggle a specific rule, you must provide its unique ID using the `--id` parameter. **Toggle Preference** ```bash aigne web prefs toggle --id ``` You can also use the alias `t`: **Toggle Preference** ```bash aigne web prefs t --id ``` ### Example To deactivate the theme preference from the example above: **Prefs Toggle --id Pref_i9j0k1l2** ```bash aigne web prefs toggle --id pref_i9j0k1l2 ``` Running `aigne web prefs list` again would show `pref_i9j0k1l2` as `false`. Running the toggle command on the same ID again would reactivate it. ## Removing a Preference To permanently delete a preference that is no longer needed, use the `remove` command. This action is irreversible. You must specify the rule to delete by providing its ID via the `--id` parameter. **Remove Preference** ```bash aigne web prefs remove --id ``` You can also use the alias `rm`: **Remove Preference** ```bash aigne web prefs rm --id ``` ### Example To permanently remove the page preference from the example above: **Prefs Remove --id Pref_a1b2c3d4** ```bash aigne web prefs remove --id pref_a1b2c3d4 ``` The specified preference will be removed from your `preferences.yml` file. ## Understanding Preference Scopes Preferences are applied based on their assigned `scope`, which determines the context in which a rule is triggered. | Scope | Description | |---|---| | global | Applies to all stages of generation and content refinement. Use for universal style or content rules. | | structure | Applies only when planning or updating the website's structure (e.g., adding, removing pages). | | page | Applies when generating or refining the content of individual pages. | | translation | Applies only during the content translation process. | | theme | Applies when generating or modifying the website's visual theme, such as colors and fonts. | ## Summary The `prefs` command is an essential tool for customizing and controlling the long-term behavior of AIGNE WebSmith. By listing, toggling, and removing preferences, you can maintain a clean and effective set of rules that ensures the AI consistently produces results aligned with your project's specific needs. --- ## Publish Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-publish-website-c47353/ Once your website is generated, the final step is to make it accessible online. This guide covers the various methods to publish your site using AIGNE WebSmith, ensuring you can choose the option that best fits your technical and budget requirements. The `aigne web publish` command is the primary tool for deploying your generated website files. Depending on your needs, you can deploy to the free WebSmith Cloud, integrate with your own existing infrastructure, or set up a new dedicated website. ### Publishing Destinations WebSmith provides three distinct publishing targets. For detailed step-by-step instructions, please refer to the specific guides for each option. ::::card-group ::link-card{title="To WebSmith Cloud" description="Publish to our free, managed hosting platform. Ideal for open-source projects, personal sites, or community sharing." icon="cloud" href="/en/docs/aigne-web-smith/guides-publish-website-to-websmith-cloud-c47353/"} ::link-card{title="To Existing Website" description="Integrate and deploy the generated pages directly onto your current, self-managed website infrastructure." icon="server" href="/en/docs/aigne-web-smith/guides-publish-website-to-existing-website-c47353/"} ::link-card{title="To New Dedicated Website" description="Create and publish to a new, fully-managed website with a custom domain and professional hosting. This is a paid service." icon="globe" href="/en/docs/aigne-web-smith/guides-publish-website-to-new-dedicated-website-c47353/"} :::: ### General Process Regardless of the destination, the publishing process is initiated with a single command. The tool will then guide you through any necessary authentication or configuration steps. 1. Generate Your Website: Before publishing, ensure your website has been created using the `aigne web generate` command. 2. Run the Publish Command: Execute the following command in your terminal: **aigne web publish** ```sh aigne web publish ``` 3. Follow Interactive Prompts: The CLI will present you with the available publishing options. If you haven't specified a target, you will be asked to select one. For first-time connections to a service, a browser window will open for authentication. ![WebSmith Publish Options](https://media.arcblock.io/lib/93/935785420285cb10.w1600.webp) 4. Validate Deployment: After the command completes, it will output a confirmation message and the live URLs for your published pages. It is recommended to visit these links to verify that the deployment was successful and the website appears as expected. ![Successful Publish Output](https://media.arcblock.io/lib/ee/ee30758408f794f2.w1600.webp) ### Summary Publishing your website is a straightforward process handled by the `aigne web publish` command. By offering multiple deployment targets, WebSmith ensures flexibility for various use cases. For specific instructions on each publishing method, refer to the detailed guides: - [To WebSmith Cloud](/en/docs/aigne-web-smith/guides-publish-website-to-websmith-cloud-c47353/) - [To Existing Website](/en/docs/aigne-web-smith/guides-publish-website-to-existing-website-c47353/) - [To New Dedicated Website](/en/docs/aigne-web-smith/guides-publish-website-to-new-dedicated-website-c47353/) --- ## To Existing Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-publish-website-to-existing-website-c47353/ This guide shows you how to publish to an ArcBlock-powered website you already operate. Publishing to your own infrastructure gives you complete control over hosting, integration, and deployment. Before proceeding, ensure your website is compatible and properly configured. ## Prerequisites To successfully publish to your own website, the following conditions must be met: ::::steps :::step{title="A Generated Website:"} You must have already generated your website pages using the `aigne web generate` command. The generated content should be present in your project's output directory. ::: :::step{title="A Blocklet Server-Powered Website:"} Your target website must be a running Blocklet application. AIGNE WebSmith integrates directly with the Blocklet Server environment. ::: :::step{title="Required Component:"} The Pages Kit component must be installed and running on your target website. This component provides the necessary APIs for AIGNE WebSmith to upload and manage your content. ::: :::: If your website is not yet set up, you can acquire the necessary components from the Blocklet Store: - [Install Pages Kit on your website](https://store.blocklet.dev/blocklets/z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o) ## Publishing Process The publishing process involves running a command, selecting the appropriate option, providing your website's URL, and authorizing the AIGNE WebSmith CLI to connect to your site. ### Step 1: Initiate the Publish Command Begin the process by running the `publish` command in your terminal from your project directory. **Publish Website** ```bash aigne web publish ``` ### Step 2: Select Publishing Option When prompted for a destination, choose Your existing website. ![Prompt showing the “Your existing website” option selected](https://media.arcblock.io/lib/37/37bb741556b9f11c.w1600.webp) ### Step 3: Provide Your Website URL Provide the full URL of the site that already runs Pages Kit when the terminal prompt asks for it. ![Prompt requesting the target website URL](https://media.arcblock.io/lib/b2/b29df027c128a1b5.w1600.webp) ### Step 4: Authorize the Publish Command For the first connection to a new website, the terminal command requires your authorization to publish content. This is a one-time setup process for each website. ::::steps :::step{title="Browser Authentication:"} Your default web browser automatically opens a page so you can grant the publish command access. ::: :::step{title="Log In:"} You will be prompted to log in to your website using your DID Wallet. ::: :::step{title="Approve Connection:"} After logging in, you must approve the request from "AIGNE WebSmith" to access your site. The request will ask for permissions to manage pages. ::: :::: Once approved, a secure access token is generated and stored locally in your home directory (`~/.aigne/web-smith-connected.yaml`). This token will be used for all subsequent publish operations to this specific URL, so you will not need to repeat the authorization step. ![Service authorization screen confirming WebSmith access](https://media.arcblock.io/lib/63/635df8119def0e1a.w1600.webp) ### Step 5: Await Confirmation After authorization, the terminal command proceeds to: 1. Bundle your generated page files and assets. 2. Upload all referenced media files. 3. Publish the page content to your website. Upon successful completion, a confirmation message will be displayed in the terminal, including the live URLs for your newly published pages. ![Terminal output confirming page and asset upload success](https://media.arcblock.io/lib/ee/ee30758408f794f2.w1600.webp) ## Troubleshooting If you encounter an error during the publishing process, refer to the common issues below. - Error: "The provided URL is not a valid website on ArcBlock platform" - - Cause: The URL you entered does not point to a valid Blocklet application. - Solution: Verify that the URL is correct and that the website is running. Ensure you have included the correct protocol (e.g., `https://`). - Error: "This website does not have required components for publishing" - - Cause: The target website is a valid Blocklet but is missing the required "Pages Kit" component. - Solution: Install the Pages Kit component on your website. You can install [here](https://store.blocklet.dev/blocklets/z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o). - Error: "Unable to connect" or "Failed to obtain access token" - - Cause: This typically indicates a network issue, or the target server is unavailable. It can also occur if you reject the authorization request in your browser. - Solution: Check your internet connection, ensure the website URL is correct and accessible, and re-run the `aigne web publish` command, making sure to approve the authorization request. After successfully publishing, you can manage your content further. To make changes to existing pages, see [Update Website](/en/docs/aigne-web-smith/guides-update-website-c47353/). --- ## To New Dedicated Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-publish-website-to-new-dedicated-website-c47353/ This guide walks you through creating and publishing to a brand-new dedicated website. This paid service provisions a fully managed hosting environment with custom domain support and dedicated resources—perfect for professional projects. The entire process is automated: run the command, complete the one-time setup and payment, and your website goes live. ## Process Overview Publishing to a new dedicated website involves a sequence of automated steps handled by the `publish` command. The command interfaces with a deployment service to provision and configure all necessary resources. The workflow is as follows: ::::steps :::step{title="Initiation"} The user runs the `aigne web publish` command. ::: :::step{title="Option Selection"} The user chooses the "New dedicated website" option from the interactive prompt. ::: :::step{title="Confirm Assets"} The user is prompted to confirm whether to include branding, navigations, and locale settings in the deployment. ::: :::step{title="Payment & Provisioning"} The user is directed to a secure web page to complete payment. The system then automatically sets up the website hosting and environment. ::: :::step{title="Content Deployment"} AIGNE WebSmith uploads and publishes the generated pages to a default project on the newly created website. ::: :::step{title="Confirmation"} The user receives the live URL for the new website. ::: :::: ## Step-by-Step Instructions To publish your website, follow these steps precisely. ### 1. Initiate the Publish Command First, ensure your website pages have been generated using the `aigne web generate` command. Once your content is ready in the output directory, execute the following command in your terminal: **Publish Website** ```bash aigne web publish ``` ### 2. Select the Publishing Option When the terminal lists publishing targets, choose New dedicated website and confirm.![Prompt showing the “New dedicated website” option highlighted](https://media.arcblock.io/lib/8a/8aafb31d05a6eb7e.w1600.webp) ### 3. Confirm Additional Assets After selecting the dedicated option, the terminal asks whether to include locales, navigation, and branding. Accept the default “Yes” so your new site launches fully configured. ![Prompt asking whether to include locales, navigation, and branding](https://media.arcblock.io/lib/b0/b0bfe4d2a2714ae1.w1600.webp) ### 4. Complete the Setup and Payment After selecting the option, the automated setup process will begin: ::::steps :::step{title="Payment"} A message will appear in your terminal indicating that the payment process is starting. A secure payment link will be opened in your default web browser. ::: :::: ![Checkout screen confirming payment for the dedicated website](https://media.arcblock.io/lib/e5/e5d22e10373c2d04.w1600.webp) ::::steps :::step{title="Provisioning"} After payment completes, WebSmith resumes automatically. The terminal waits for the service to be provisioned, started, and verified—no further action is required on your part. ::: :::: ![Payment confirmation and success message](https://media.arcblock.io/lib/70/70af154c6a1840bc.w1600.webp) ::::steps :::step{title="Completion"} When the setup is complete, the terminal displays the live URL plus a subscription-management link. ::: :::: ![Terminal output showing provisioning progress and the live URL](https://media.arcblock.io/lib/71/713f433202bad291.w1600.webp) ### 5. Authorize the Hosting Service Before WebSmith can upload content, approve the publish permission request. The terminal launches a browser, you grant access, and the resulting token is saved for future runs. ![Service authorization screen confirming WebSmith access](https://media.arcblock.io/lib/63/635df8119def0e1a.w1600.webp) ### 6. Automatic Content Publishing Once the site is provisioned and authorization succeeds, AIGNE WebSmith uploads your generated pages and media assets automatically. ![Terminal output confirming page and asset upload success](https://media.arcblock.io/lib/ee/ee30758408f794f2.w1600.webp) ## Resuming an Incomplete Setup If a previous attempt to create a dedicated website was initiated but not completed (e.g., the payment process was abandoned), the system will save the session details. The next time you run `aigne web publish`, you will see an additional option to resume the process. ![Prompt showing option to resume previous website setup](https://media.arcblock.io/lib/93/935785420285cb10.w1600.webp) Selecting this "Resume" option allows you to continue from where you left off without needing to start over or pay again if the payment was already processed. The system will use the saved `checkoutId` to restore the previous session and complete the website setup. ## Summary You have successfully published your project to a new, dedicated website. Your content is now live and accessible at the provided URL. To make changes, you can either update the content with `aigne web update` or regenerate the entire site structure with `aigne web generate`, followed by another `aigne web publish` command. The system will use the saved configuration to publish updates to the same website. --- ## To WebSmith Cloud URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-publish-website-to-websmith-cloud-c47353/ This guide walks you through publishing to WebSmith Cloud—a free hosting service that makes your website publicly accessible without managing any infrastructure. It's the recommended starting point for new users and perfect for open-source projects, portfolios, or community-focused sites. ## Prerequisites Before proceeding with the publication process, ensure that you have already generated your website's pages. If you have not completed this step, please do so by running the following command: **Generate Website** ```bash aigne web generate ``` ## Publishing Procedure The publishing process is initiated through a single command. The system will then guide you through the necessary selections and authorizations. ### Step 1: Execute the Publish Command Open your terminal, navigate to your project's root directory, and execute the `publish` command. **Publish Website** ```bash aigne web publish ``` You can also use the aliases `pub` or `p`. ### Step 2: Select the Publishing Platform After executing the command, you will be presented with a list of publishing options. Select WebSmith Cloud to use the free hosting option. ![Prompt showing WebSmith Cloud selected as the publish destination](https://media.arcblock.io/lib/de/deba2c42f80e591d.w1600.webp) ### Step 3: Authorize AIGNE WebSmith (First-Time Setup Required) If this is your first time publishing to WebSmith Cloud, the command-line tool needs to be authorized to publish on your behalf. This is a one-time security procedure. 1. A secure authentication URL will automatically open in your default web browser. 2. You will be prompted to log in to your account and approve the connection request from "AIGNE WebSmith". 3. Once you approve, you can close the browser tab and return to the terminal. The tool will securely store your authorization credentials, so you will not need to repeat this step for subsequent publications. ![Browser window requesting authorization for the WebSmith Cloud deployment](https://media.arcblock.io/lib/8d/8ddf5f5d4dafa4ec.w1600.webp) ### Step 4: Await Publication The terminal now handles the entire publication process automatically. This includes: - Bundling your page and content files. - Uploading all associated media assets. - Deploying the files to the WebSmith Cloud servers. This process may take a few minutes, depending on the size of your website. ## Reviewing Your Live Website Upon successful completion, the terminal displays a confirmation message. This message includes the total number of pages and assets published, along with the direct URLs to access your live website. ![Terminal output confirming page and asset upload success](https://media.arcblock.io/lib/ee/ee30758408f794f2.w1600.webp) You can now visit these URLs in your web browser to view your published website. You have successfully published your website to WebSmith Cloud. If you need to make changes, you can modify your content and run the `publish` command again, or use the `update` command for more specific modifications. For more details, see [Update Website](/en/docs/aigne-web-smith/guides-update-website-c47353/). For alternative deployment targets, refer to the following guides: - [To Existing Website](/en/docs/aigne-web-smith/guides-publish-website-to-existing-website-c47353/) - [To New Dedicated Website](/en/docs/aigne-web-smith/guides-publish-website-to-new-dedicated-website-c47353/) --- ## Add Page URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-add-page-c47353/ Expanding your website is straightforward with AIGNE WebSmith. This guide explains how to use the `aigne web add-page` command to seamlessly integrate new pages into your site's structure, automatically updating content and internal links. The `aigne web add-page` command provides an interactive way to expand your website. It allows you to describe new pages in natural language, and WebSmith handles the process of creating the page, generating its content, and intelligently updating existing pages with relevant links to the new content. ## Command Usage To start adding pages, navigate to your project's root directory and run the following command: **aigne web add-page** ```sh aigne web add-page ``` Alternatively, you can use the shorter alias `add`: **aigne web add** ```sh aigne web add ``` ## Process When you run the `add-page` command, WebSmith initiates a comprehensive, automated workflow. The process is broken down into the following steps: ### 1. Add New Pages The command first prints the current sitemap, giving you a clear overview of your existing pages. You are then prompted to describe the page you wish to add, specifying its title and location (e.g., "add a pricing page under the main services page"). You can add multiple pages in a single session. After each addition, the tool displays the updated structure and prompts for the next one. To finish adding pages, simply press Enter at an empty prompt. WebSmith then generates the content for each new page based on your project's source materials. The following is a use case for adding a page: **Add 'Team' and 'Careers' pages** ```text - My SaaS Platform [/home] - Features [/features] - About Us [/about] You can add a new page. • e.g. 'add an FAQ page under the About Us page' Press Enter to finish: add a 'Team' page under '/about' - My SaaS Platform [/home] - Features [/features] - About Us [/about] - Team [/about/team] You can continue adding pages, or press Enter to finish: add a 'Careers' page under '/about' ``` ### 2. Review Pages for Link Insertion After the new pages are created, WebSmith analyzes your existing content to identify relevant places to insert links to your new content. This ensures seamless navigation and helps users discover the new pages. The system will present you with a list of pages where links can be added, allowing you to review and confirm the changes before they are applied. Here is a use case for reviewing pages for link insertion: **Reviewing Link Suggestions** ```text ? Select pages that need new links added (all selected by default, press Enter to confirm, or unselect all to skip): ◉ About Us (/about) ◯ My SaaS Platform (/home) Do you want to proceed with these changes? (Y/n) ``` ### 3. Output Summary Once the structure is finalized and links are inserted, a summary report is displayed. This report lists the new pages created and any existing pages that were updated with new links. If your site uses multiple languages, the new pages and updated links are automatically included in the translation workflow. The following is a use case for the output summary: **Final Summary** ```text --- 📊 Summary ✨ Newly Generated Pages: Total: 2 page(s) 1. /about/team Title: Our Team Description: Meet the dedicated team behind our project, driving innovation... 🔗 Pages Updated with New Links: Total: 1 page(s) 1. /about Added links to: /about/team ``` ## Next Steps ::::card-group ::link-card{title="Update Page" description="Learn how to refine the text and details on individual pages using natural language commands." icon="file-text" href="/en/docs/aigne-web-smith/guides-update-website-update-page-c47353/"} ::link-card{title="Remove Page" description="Learn how to remove an existing page from your website structure." icon="file-minus" href="/en/docs/aigne-web-smith/guides-update-website-remove-page-c47353/"} :::: --- ## Update Website URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-c47353/ Use this guide to select the right update workflow and then dive into the detailed sub-guides for structure or page-level changes. Once your website is generated, you will inevitably need to make changes. AIGNE WebSmith provides a clear and structured approach to keeping your site current. Updates typically fall into two categories: modifying the overall structure of your site or refining the content within individual pages. This section provides a high-level overview of both processes. For detailed, step-by-step instructions, please refer to the specific sub-documents linked below. ::::card-group ::link-card{title="Update Page" description="Learn how to refine the text and details on individual pages using natural language commands." icon="file-text" href="/en/docs/aigne-web-smith/guides-update-website-update-page-c47353/"} ::link-card{title="Add Page" description="Learn how to add a new page to your website structure." icon="file-plus" href="/en/docs/aigne-web-smith/guides-update-website-add-page-c47353/"} ::link-card{title="Remove Page" description="Learn how to remove an existing page from your website structure." icon="file-minus" href="/en/docs/aigne-web-smith/guides-update-website-remove-page-c47353/"} ::link-card{title="Manage Update History" description="Review everything the `history` command captured so you can explain what changed and when." icon="clock" href="/en/docs/aigne-web-smith/guides-update-website-manage-update-history-c47353/"} :::: ## Summary By separating structural adjustments, page-level refinements, and the audit trail, WebSmith offers a logical and efficient workflow for managing your website. After making your desired changes, the next step is often to make them live. For guidance on this, see the [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/) article. --- ## Manage Update History URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-manage-update-history-c47353/ Use this guide to audit everything WebSmith has changed. The `aigne web history` command records every generate or update action, so you always know what changed, when it happened, and why feedback was applied. This guide lives inside the broader Update Website workflow. Run it whenever you need a paper trail before publishing, reviewing with teammates, or rolling back edits. ## View the history log Show the entire update log (most recent first) with: **View History Log** ```bash aigne web history view ``` Aliases `log` and `list` produce the same output: **View History Log (Alias)** ```bash aigne web history log ``` If no updates exist yet, WebSmith prints `No update history found`. ## Understand each entry Every line describes one change event and follows the same structure. | Field | Description | |---|---| | Short hash | Deterministic identifier derived from the timestamp. Use it when discussing a specific update with your team. | | Date | Relative timestamp (for example, `5 minutes ago` or `2 days ago`). Entries older than a week show the calendar date. | | Operation | `structure_update` for sitemap changes or `page_update` for individual page edits. | | Page path | Only shown for `page_update` entries and appears in parentheses (such as `(about-us)`). | | Feedback | The summary you provided when running `aigne web update`, captured so future readers understand the intent. | ### Sample output ```text 📜 Update History e5c7a91 5 minutes ago page_update (about-us): Refined the company mission statement a3b4f8e 2 hours ago page_update (services): Added new section for consulting services 1d9c0b2 1 day ago structure_update: Added a new "Careers" page to the main menu f4e5a67 3 days ago page_update (contact): Updated the main office phone number ``` Use the history log before publishing to confirm which edits are about to go live, or after publishing to answer stakeholder questions about when something changed. ## Related workflows - [Update Structure](/en/docs/aigne-web-smith/guides-update-website-update-structure-c47353/) – regenerate navigation and site maps. - [Update Page](/en/docs/aigne-web-smith/guides-update-website-update-page-c47353/) – refine copy on individual pages. --- ## Remove Page URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-remove-page-c47353/ Need to clean up your website's structure? This guide explains how to use the `aigne web remove-page` command to safely delete pages, automatically find any broken links this creates, and regenerate the affected content to maintain site integrity. ## Overview The `remove-page` command provides an interactive way to remove one or more pages from your website. A key feature of this command is its ability to detect and repair broken internal links that result from page deletion. After you remove pages, WebSmith automatically scans the remaining content for any links that pointed to the deleted pages. It then prompts you to regenerate the affected pages, ensuring your site's navigation remains consistent and error-free. This process helps maintain a clean and professional website by preventing users from encountering dead links. ## The Process To start the process, run the following command in your terminal: **aigne web remove-page** ```sh aigne web remove-page ``` You can also use the aliases `remove` or `rm`: **aigne web rm** ```sh aigne web rm ``` ### Step 1: Select Pages to Remove The command will display a list of all pages in your current website structure. You can navigate this list using the arrow keys and select the pages you wish to remove by pressing the spacebar. **Select pages to remove** ```text ? Select pages to remove (Press Enter with no selection to finish): ❯ ◯ Smart Video Streaming Credit Service [/home] ◉ About the Project [/about] ◯ Frequently Asked Questions [/about/faq] ``` Once you have selected all the pages you want to delete, press `Enter` to confirm. If you decide not to remove any pages, you can press `Enter` without making a selection to exit the process. The tool will then ask for confirmation before proceeding with the deletion. ### Step 2: Automatic Link Correction (Optional) After removing the selected pages, WebSmith scans your remaining pages for any internal links that now point to non-existent content. If broken links are found, you will be presented with a list of the affected pages. By default, all of these pages are selected to be fixed. You can review the list and press `Enter` to allow WebSmith to regenerate these pages, automatically removing the invalid links. If you prefer to handle the broken links manually, you can unselect all pages to skip this step. **Select pages to fix** ```text ? Select Pages with Invalid Links to Fix (all selected by default, press Enter to confirm, or unselect all to skip): ❯ ◉ Home (home.md) Invalid Links(1): /about ``` ### Step 3: Review the Summary Once the process is complete, a summary will be displayed in the terminal. This summary provides: - A list of all pages that were successfully removed. - A list of all pages that were regenerated to fix broken links. **Summary of remove page operation** ```text --- 📊 Summary 🗑️ Removed Pages: Total: 1 page(s) 1. /about ✅ Pages fixed (Removed invalid links): Total: 1 page(s) 1. /home Title: Home Invalid links fixed: /about ``` This ensures you have a clear record of all changes made to your website structure and content. ## Summary The `aigne web remove-page` command is a reliable tool for maintaining your website's structure. It not only simplifies the process of deleting pages but also includes an intelligent link-checking feature to preserve the integrity of your site's navigation. For related tasks, see the following guides: ::::card-group ::link-card{title="Add Page" description="Learn how to add new pages to your website structure." icon="file-plus" href="/en/docs/aigne-web-smith/guides-update-website-add-page-c47353/"} ::link-card{title="Update Page" description="Refine the content and details within an individual webpage." icon="edit" href="/en/docs/aigne-web-smith/guides-update-website-update-page-c47353/"} :::: --- ## Update Page URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-update-page-c47353/ Use this guide when you need to run `aigne web update` against a single page—rewriting sections, inserting new modules, reordering blocks, or trimming obsolete content—without changing the rest of the site. This process is distinct from modifying the overall site map. For instructions on adding, removing, or reorganizing pages, refer to the [Update Structure](/en/docs/aigne-web-smith/guides-update-website-update-structure-c47353/) guide. ## The Update Process Content updates are initiated using the `aigne web update` command. The process is interactive, allowing you to provide feedback in natural language, which WebSmith then converts into structured changes on the selected page. **Update Page** ```bash aigne web update ``` The command can also be invoked with its alias, `up`. The standard workflow is as follows: ::::steps :::step{title="Execute the Command"} Run `aigne web update`. ::: :::step{title="Select Page"} WebSmith presents a list of existing pages. Select the single page you wish to modify. ::: :::step{title="Provide Feedback"} Enter natural language instructions describing the changes you want to make. For example, “Change the hero headline to ‘Instant AI Websites’” or “Add a three-column feature section after Benefits.” ::: :::step{title="Processing"} WebSmith analyzes your request and uses its update tools to apply the changes to the page’s content structure. ::: :::step{title="Review and Save"} The updated page content is saved. You can regenerate or publish to see the new copy reflected in rendered pages. ::: :::: ![Interactive prompt showing page selection and feedback entry for updates](https://media.arcblock.io/lib/c9/c94310712109a8b2.w1600.webp) ## Command Parameters For non-interactive or scripted use, you can provide feedback and other parameters directly as command-line arguments. - **--pages** `array` — Specify one or more page paths to update. If not provided, WebSmith prompts you to select a page interactively. - **--feedback** `string` — Provide content feedback directly. Useful for scripted updates. - **--glossary** `string` — A glossary of terms to ensure consistent terminology during content generation. You can provide a path to a file using the @ syntax. ## Content Modification Capabilities The update workflow uses tool-based operations. Align your feedback to these capabilities for predictable results. | Action | Description | Example Feedback | |---|---|---| | Add Section | Adds a new content block. Specify the content and its position. | “Add a ‘Customers’ section after Features with three testimonials.” | | Delete Section | Removes an existing block by name. | “Remove the ‘Legacy Support’ section.” | | Update Section | Modifies content within a block. | “In the ‘Pricing’ section, change the headline to ‘Predictable pricing for teams.’” | | Move Section | Reorders sections. | “Move ‘FAQ’ so it appears before the final CTA.” | | Update Metadata | Updates page metadata such as title or description. | “Set the page title to ‘Platform Overview’.” | ## Example Feedback Prompts **Example Feedback** ```text "Add a four-step walkthrough section after the hero for onboarding instructions." "Remove the case-study section that references Legacy API clients." "Change the CTA in the hero to 'See it in action' and adjust the subheading to mention 5-minute setup." ``` ## Summary Updating page content is an iterative process driven by clear instructions. By aligning your feedback to WebSmith’s page-update capabilities, you can quickly refine copy, re-order sections, and keep your site accurate without affecting the rest of the website. For structural changes, see the [Update Structure](/en/docs/aigne-web-smith/guides-update-website-update-structure-c47353/) guide. For publishing updates, visit [Publish Website](/en/docs/aigne-web-smith/guides-publish-website-c47353/). --- ## Update Structure URL: https://www.arcblock.io/en/docs/aigne-web-smith/guides-update-website-update-structure-c47353/ Follow this guide when you want to reshape the sitemap with `aigne web generate`, such as adding or removing pages before approving the plan. Modifying the structure of your website—such as adding new pages, removing obsolete ones, or reorganizing the navigation—is a critical task for keeping your content relevant and user-friendly. AIGNE WebSmith facilitates this process through an AI-driven workflow that interprets natural language feedback to perform precise structural changes. This document explains how to modify your site's structure using the `aigne web generate` command. During this process, an AI agent interprets your feedback in natural language to add, remove, update, or move pages. Understanding the available operations helps you provide clear instructions to achieve your desired site layout. The primary command for applying structural changes is `aigne web generate`. For more details on the creation process itself, see [Create Website](/en/docs/aigne-web-smith/guides-create-website-c47353/). ## The Structure Update Process When you run the `aigne web generate` command, the system first analyzes your content sources and proposes a website structure. You are then given an opportunity to review and modify this structure interactively. ## Interactive Update Workflow The process for updating your website's structure is interactive. Here is a summary of the workflow: 1. Initiate Generation: Run the generate command in your terminal. **Run command** ```bash aigne web generate ``` 2. Review Proposed Structure: After analyzing your sources, the terminal displays the proposed structure and asks for your input. 3. Provide Natural Language Feedback: At the prompt, type your desired changes in natural language. For example: > "Add a 'Contact Us' page at the top level with the path `/contact`. Also, remove the page at `/about/old-team`." > 4. Review and Approve: The AI processes your feedback, applies the necessary changes, and displays the revised structure. You can then approve the changes to finalize the process or provide more feedback to refine it further. ## Core Structural Operations The AI agent understands four fundamental operations for modifying the website structure. Providing clear feedback that aligns with these operations will yield the most accurate results. | Operation | Description | Key Parameters | |---|---|---| | Add | Creates a new page in the website structure. | `title`, `description`, `path`, `parentId`, `sourceIds` | | Delete | Removes an existing page from the structure. | `path` | | Update | Modifies the metadata of an existing page. | `path`, `title` (optional), `description` (optional), `sourceIds` (optional) | | Move | Relocates a page to a different parent, changing its path. | `path`, `newParentId`, `newPath` | ### Examples of Feedback Here are some examples of how you can phrase your feedback to perform specific structural changes: - Adding a page: > "Add a new page titled 'Our Team' under the '/about' section. The path should be `/about/team`." > - Deleting a page: > "Please remove the 'Legacy Products' page located at `/products/legacy`." > - Updating a page: > "Update the title for the page at `/services` to 'Our Professional Services'." > - Moving a page: > "Move the 'Careers' page, currently at `/careers`, so it becomes a child of the '/about' page. Its new path should be `/about/careers`." > ## Summary This interactive process ensures your website's structure is always organized, up-to-date, and aligned with your goals. The system handles the technical details, allowing you to focus on the logical arrangement of your content. For more hands-on guidance, please refer to the following sections: - [Create Website](/en/docs/aigne-web-smith/guides-create-website-c47353/) - [Interactive Mode](/en/docs/aigne-web-smith/guides-interactive-mode-c47353/) --- ## Overview URL: https://www.arcblock.io/en/docs/aigne-web-smith/overview-c47353/ This document provides a high-level introduction to AIGNE WebSmith. By the end, you will understand its core purpose, key features, and the fundamental workflow it uses to automate the creation of professional websites, from initial planning to final publication. AIGNE WebSmith is an AI-driven tool that automates the creation of professional, SEO-optimized websites. It generates complete content and templates based on your provided source materials and can publish the final site directly. The system is designed to streamline the entire web development process, minimizing manual effort and technical requirements. ## Key Features WebSmith offers a comprehensive set of features for automated website creation and management. The system is organized around four main capabilities: AI-driven generation, a professional template system, quality assurance, and direct publishing. | Feature Area | Description | |---|---| | AI-Powered Generation | Utilizes AI to analyze requirements, plan an optimal site structure, generate detailed content for all pages in a single operation, and apply SEO best practices. It supports both English and Chinese content generation. | | Professional Templates | Creates templates compatible with Pages Kit, using a component-based design with elements like Hero, CTA, and FAQ. The templates are responsive, adapting to both mobile and desktop displays. | | Quality Assurance | Includes an automated evaluation system to assess website architecture, user experience, and content consistency. It is supported by a suite of over 32 test cases covering core functions. | | One-Click Publishing | Enables direct, batch publishing of multi-page websites to Pages Kit. It provides status monitoring and delivers public access links immediately after a successful deployment. | ## How It Works WebSmith employs a series of specialized AI agents that work sequentially to build and deploy a website. Each agent is responsible for a specific stage of the process, ensuring a structured and reliable workflow from conception to publication. The following diagram illustrates this sequential process: ![Overview](https://media.arcblock.io/lib/a8/a8e8c09c4c9e7c6e.w1600.webp) The process is as follows: ::::steps :::step{title="Structure Planning"} An agent analyzes your project requirements to design an intelligent and logical website architecture. ::: :::step{title="Content Generation"} Based on the planned structure, another agent generates high-quality, relevant content for each page. ::: :::step{title="Template Generation"} A third agent takes the generated content and assembles it into professional, component-based templates. ::: :::step{title="Evaluation & Publishing"} Finally, evaluation agents assess the quality of the output before the publishing agent uploads the completed website. ::: :::: This modular, agent-based architecture ensures that each step is handled by a specialized process, resulting in a consistent and high-quality final product. ## Core Components The functionality of WebSmith is delivered through a set of distinct command-line interface (CLI) commands. Each command corresponds to a core component or workflow within the system. ::::card-group ::link-card{title="Generate" description="Generates a complete website, including structure and content, from user-defined requirements." icon="bot" href="/en/docs/aigne-web-smith/guides-create-website-c47353/"} ::link-card{title="Publish" description="Publishes the generated website to various targets, including WebSmith Cloud or your own infrastructure." icon="rocket" href="/en/docs/aigne-web-smith/guides-publish-website-c47353/"} ::link-card{title="Update" description="Modifies the content or structure of an existing website based on new feedback or requirements." icon="edit" href="/en/docs/aigne-web-smith/guides-update-website-c47353/"} ::link-card{title="Translate" description="Translates existing website content into multiple languages, such as Chinese, Japanese, French, and German." icon="globe" href="/en/docs/aigne-web-smith/guides-localize-website-c47353/"} ::link-card{title="Theme" description="Manages visual themes by generating and applying different styles and color schemes to the website." icon="palette" href="/en/docs/aigne-web-smith/guides-customize-theme-c47353/"} ::link-card{title="Component" description="Manages the component library used to build the visual elements of your website." icon="book-open" href="/en/docs/aigne-web-smith/advanced-features-use-custom-component-libraries-c47353/"} :::: ## Summary This overview has introduced the primary functions and architecture of AIGNE WebSmith. You should now have a foundational understanding of what WebSmith is, its main features, and the commands used to interact with it. For your next steps, we recommend proceeding to the [Getting Started](/en/docs/aigne-web-smith/getting-started-c47353/) guide, which provides a step-by-step tutorial to install, configure, and generate your first website. --- ## Reference URL: https://www.arcblock.io/en/docs/aigne-web-smith/reference-c47353/ This section provides detailed technical material for AIGNE WebSmith. It is designed for users seeking specific, in-depth information about commands, configuration options, material preparation, and licensing. For practical, step-by-step guides, please consult the [Getting Started](/en/docs/aigne-web-smith/getting-started-c47353/) or [Guides](/en/docs/aigne-web-smith/guides-c47353/) sections. The reference materials are organized into the following detailed pages: ::::card-group ::link-card{title="Command Reference" description="A comprehensive guide to all available commands, their aliases, parameters, and usage examples." icon="terminal" href="/en/docs/aigne-web-smith/reference-command-c47353/"} ::link-card{title="Config Reference" description="Configuration options and settings for customizing WebSmith behavior, including project structure, generation preferences, and deployment settings." icon="wrench" href="/en/docs/aigne-web-smith/reference-config-c47353/"} ::link-card{title="Prepare Materials" description="A repeatable process for gathering briefs, source docs, and evidence so WebSmith can generate accurate, high-quality pages." icon="folder" href="/en/docs/aigne-web-smith/reference-prepare-materials-c47353/"} ::link-card{title="Trouble Shooting" description="Solutions to common problems with configuration, generation, publishing, and translation. Includes error messages, causes, and step-by-step fixes." icon="wrench" href="/en/docs/aigne-web-smith/reference-trouble-shooting-c47353/"} :::: ## Licensing AIGNE WebSmith is licensed under the Elastic License 2.0. This license grants you a non-exclusive, royalty-free, worldwide license to use, copy, distribute, and prepare derivative works of the software, subject to specific conditions. Key limitations include: - Hosted Services Restriction: You may not provide the software to third parties as a hosted or managed service where the service provides access to any substantial set of the software's features or functionality. - License Key Integrity: You may not move, change, disable, or circumvent the license key functionality in the software. - Notice Preservation: You are not permitted to alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. For a complete understanding of your rights and obligations, please review the full license terms available at the official Elastic License 2.0 URL. --- ## Command Reference URL: https://www.arcblock.io/en/docs/aigne-web-smith/reference-command-c47353/ This reference lists all commands available in the AIGNE WebSmith CLI, including their aliases, parameters, and usage examples. The standard syntax for CLI operations is as follows: **Run Command** ```bash aigne web [subcommand] [parameters] ``` Executing `aigne web` without a command initiates interactive mode. ## Main Commands The following table summarizes the primary commands. Each command is detailed further in the sections below. | Command | Aliases | Description | |---|---|---| | [generate](#generate) | `gen`, `g` | Generates a complete website based on a configuration file. | | [publish](#publish) | `pub`, `p` | Publishes the generated website to a Pages Kit instance. | | [update](#update) | `up` | Modifies existing website content based on user feedback. | | [translate](#translate) | | Translates website pages into different languages. | | [theme](#theme) | | Manages website visual themes, including generation and application. | | [component](#component) | `comp` | Manages the component library used to build the website. | | [chat](#chat) | | Starts interactive mode for website management (default). | | [prefs](#prefs) | | Manages saved user preferences learned from feedback. | | [history](#history) | | Displays a log of previous updates made to the website. | | [clear](#clear) | | Removes generated files, workspace data, or configuration settings. | ### generate The `generate` command orchestrates the creation of a complete website, from planning the site structure to generating page content and templates based on a specified configuration file. Aliases: `gen`, `g` Usage: **Generate** ```bash aigne web generate ``` Parameters: - **config** `string` — Specifies the file path for the website configuration. This is typically provided automatically. - **glossary** `string` — Path to a glossary file to ensure consistent terminology. Use the format @. - **forceRegenerate** `boolean` — Forces the regeneration of all pages, overwriting any existing generated content. ### publish The `publish` command uploads the generated website files to a Pages Kit instance. It manages the batch upload process and provides status monitoring. Aliases: `pub`, `p` Usage: **Publish** ```bash aigne web publish --appUrl "https://example.com" ``` Parameters: - **appUrl** `string` — The target base URL of the Pages Kit website where the pages will be published. - **with-navigations** `string` (default: `menu`) — Publishes navigation data. Accepted values are 'flat' or 'menu'. - **with-locales** `boolean` — Publishes website locale and language settings when set to true. ### update The `update` command modifies the content of an existing website based on user-provided feedback. It can be used to refine text, add or remove sections, or alter page structures. Alias: `up` Usage: **Update** ```bash aigne web update --pages "/about" --feedback "Add a mission statement." ``` Parameters: - **pages** `array` — An array of page paths to be updated (e.g., [\ - **feedback** `string` — A description of the required changes or improvements for the specified pages. - **glossary** `string` — Path to a glossary file for consistent terminology. Use the format @. ### translate The `translate` command translates the content of existing website pages into one or more specified languages. Usage: **Translate** ```bash aigne web translate --pages "/home" --langs "fr,de,es" ``` Parameters: - **pages** `array` — An array of page paths to be translated. - **langs** `array` — An array of language codes. Available languages: en, zh, zh-TW, ja, fr, de, es, it, ru, ko, pt, ar. - **feedback** `string` — Specific instructions to guide and improve the quality of the translation. - **glossary** `string` — Path to a glossary file for consistent translation. Use the format @. ### theme The `theme` command manages website visual themes, including their generation and application. #### Subcommands `generate` Generates a new theme based on the website's design and user suggestions. Alias: `gen` Usage: **Theme Generate** ```bash aigne web theme generate --name "CustomTheme" ``` - **name** `string` — A name for the new theme. - **config** `string` — The file path of the website configuration to use as a basis for the theme. `apply` Applies a previously generated theme to the website. Alias: `a` Usage: **Apply Theme** ```bash aigne web theme apply ``` This subcommand does not have any specific parameters. It applies the currently configured theme. ### component The `component` command manages the component library for the website. Alias: `comp` #### Subcommands `pull` Pulls components from a specified URL to update the local component library. Usage: **Component Pull** ```bash aigne web component pull --url "https://your-pages-kit/api/..." ``` - **url** `string` *(required)* — The full URL from which to pull the component library. `list` Lists the components available in the current library. Aliases: `ls`, `l` Usage: **Component List** ```bash aigne web component list ``` This subcommand does not take any parameters. ### chat The `chat` command starts an interactive session for generating, updating, and managing the website conversationally. This is the default command executed when `aigne web` is run without specifying another command. Usage: **Command** ```bash aigne web ``` This command does not take any parameters. ### prefs The `prefs` command manages user preferences that WebSmith learns from feedback to customize AI behavior. #### Subcommands `list` Lists all saved user preferences. Alias: `ls` Usage: **List Preferences** ```bash aigne web prefs list ``` This subcommand does not take any parameters. `remove` Removes one or more specified preferences. Alias: `rm` Usage: **Prefs Remove** ```bash aigne web prefs remove --id "pref_abc123" ``` - **id** `array` *(required)* — An array of preference IDs to be removed. `toggle` Toggles the active status of one or more preferences. Alias: `t` Usage: **Prefs Toggle** ```bash aigne web prefs toggle --id "pref_abc123" ``` - **id** `array` *(required)* — An array of preference IDs whose status will be toggled. ### history The `history` command is used to view the update history of the website content and structure. #### Subcommands `view` Displays the update history in a compact, log-style format. Each entry includes a hash, date, operation, and the associated feedback. Aliases: `log`, `list` Usage: **History View** ```bash aigne web history view ``` This subcommand does not take any parameters. ### clear The `clear` command removes generated files, workspace data, or configuration settings from the project directory. Usage: **Clear** ```bash aigne web clear --targets "generatedPages" "websiteConfig" ``` Parameters: - **targets** `array` — An array of items to clear without prompting. Valid items are: websiteStructure, generatedPages, websiteConfig, deploymentConfig, authTokens, mediaDescription, translationCaches. - **pagesDir** `string` — Overrides the default directory path for source pages. - **tmpDir** `string` — Overrides the default directory path for the temporary workspace. - **outputDir** `string` — Overrides the default directory path for generated pages. - **configPath** `string` — Overrides the default path for the configuration file. ## Summary This reference guide has detailed the primary commands and parameters for the AIGNE WebSmith CLI. For task-oriented instructions, refer to the guides in the [Guides](/en/docs/aigne-web-smith/guides-c47353/) section of the documentation. --- ## Config Reference URL: https://www.arcblock.io/en/docs/aigne-web-smith/reference-config-c47353/ The `config.yaml` file is the central control panel for your website generation. Understanding its settings allows you to customize every aspect of the AI's output, from page structure to content tone. This guide provides a complete, field-by-field reference to help you modify your site with precision. ## Overview The `config.yaml` file is the primary configuration source for AIGNE WebSmith. It uses the YAML format to store all the parameters the AI agent needs to generate your website. Every time you run a command like `generate` or `update`, WebSmith reads this file to understand your requirements. - File Name: `config.yaml` - Location: `.aigne/web-smith/config.yaml` (relative to your project's root directory) - Format: YAML (UTF-8) This file controls the website's purpose, target audience, content generation rules, page structure, multilingual support, and deployment settings. ### Creating and Updating the Configuration The `config.yaml` file is created automatically when you first use WebSmith. Creation: You can create the file in two ways: ::::steps :::step{title="During the first generation:"} Running `aigne web generate` in a new project will launch an interactive wizard to create the `config.yaml` file before starting the generation process. ::: :::step{title="Separately:"} Running `aigne web init` launches the same wizard to create the configuration file without immediately generating the site. ::: :::: **aigne web init** ```sh aigne web init ``` ![AIGNE WebSmith configuration wizard](https://media.arcblock.io/lib/11/114809cb26a0ee87.w1600.webp) Updating: You can update your configuration using one of two methods: ::::steps :::step{title="Directly edit the file:"} Open `.aigne/web-smith/config.yaml` in a text editor and modify the fields. ::: :::step{title="Use the interactive wizard:"} Run `aigne web init` again. The wizard will load your existing settings and guide you through updating them. ::: :::: ## Configuration Parameters The fields in `config.yaml` are organized into functional groups. The following sections provide a detailed explanation of each parameter. ### Project Basics This group defines your project's identity, which is used for branding, SEO, and social media sharing. - **projectName** `string` *(required)* ### Site Strategy These fields define the high-level strategy for the AI, influencing the site's purpose, content tone, and overall structure. - **pagePurpose** `array` *(required)* — Defines the primary goal of the website, which influences the page structure and components used. Possible values include landingPage, ecommerce, saas, portfolio, corporate, blog, nonprofit, and education. - **targetAudienceTypes** `array` *(required)* — Specifies the target audience, which affects the AI's tone, complexity, and examples. Possible values include customers, businessOwners, marketers, designers, developers, investors, jobSeekers, students, and generalPublic. - **websiteScale** `string` (default: `standard`) — Controls the number of pages and navigation complexity. Options are: singlePage (one scrollable page), minimal (2-6 pages), standard (7-12 pages, recommended), comprehensive (12+ pages), or aiDecide (lets the AI choose). - **rules** `string` — Provides detailed, multi-line instructions for the AI on content structure, tone, and style. This is a critical field for guiding the generation process to match your specific requirements. Supports Markdown format. ### Languages Configure the primary language and any additional languages for translation. - **locale** `string` (default: `en`) — The primary language for the website's base content, specified using an IETF language code (e.g., en, zh, ja). - **translateLanguages** `array` — A list of additional language codes to translate the site into. Each language code will generate a full, translated version of the site structure. ### Data Sources These fields specify the content and data that the AI agent will use as reference material. - **sourcesPath** `array` *(required)* — An array of local directory and file paths for the AI to analyze. This is the most important field for content quality, as the AI uses only these sources as references. Include documentation, READMEs, and other key project files. - **defaultDatasources** `array` — An array of file paths that are injected into the context of every page. This is useful for shared data like a media.md file that lists image locations and descriptions. ### Output & Deployment Configure output directories and deployment URLs. - **pagesDir** `string` (default: `./aigne/web-smith/pages`) — The output directory where generated site files (e.g., page.yaml) are stored. - **appUrl** `string` — The final deployment URL of your website. This is used by the publish command to determine the deployment target. ### Media & Display These settings control how media assets like images are handled. - **media.minImageWidth** `integer` (default: `800`) — The minimum width in pixels for an image to be considered for use on the website. This helps filter out low-quality or small images. ### System-Managed Fields These fields are typically managed by WebSmith and do not require manual editing. - **lastGitHead** `string` — The Git commit hash of the last generation, used for incremental updates. - **checkoutId** `string` — A temporary variable used during development. - **shouldSyncAll** `string` — A temporary variable used during development. - **navigationType** `string` — A temporary variable used during development. ## Applying Changes Changes to the `config.yaml` file are not applied automatically. You must run the appropriate command to see your modifications take effect. The command needed depends on which field you changed. | Field(s) | Command to Apply Changes | Notes | |---|---|---| | `pagePurpose`, `targetAudienceTypes`, `websiteScale`, `locale` | `aigne web clear && aigne web generate` | These require a full regeneration to restructure the site correctly. | | `rules`, `media.minImageWidth`, `defaultDatasources` | `aigne web update` | Updates existing content without a full regeneration. | | `sourcesPath` | `aigne web clear && aigne web generate` or `aigne web update` | New sources are analyzed to improve content during updates. | | `translateLanguages` | `aigne web translate` | Adds new language versions based on the updated list. | | `projectName`, `projectDesc`, `projectLogo`, `projectCover`, `appUrl` | `aigne web publish` | These fields are primarily used during the publishing process. | ## Full Configuration Example The following is a complete `config.yaml` file from the AIGNE WebSmith project itself, demonstrating a real-world configuration. **config.yaml** ```yaml projectName: AIGNE WebSmith projectDesc: "AI-powered website generation tool built on the AIGNE Framework" projectLogo: https://www.arcblock.io/content/uploads/2e5edbac4a7d5310c117d09601811c.png projectId: pg4d0000-0000-4000-a000-000000000000 projectSlug: / pagePurpose: - landingPage targetAudienceTypes: - customers websiteScale: singlePage rules: | ### I. Core Messaging & Strategy: Foundational elements that define *what* you communicate to the user. 1. Answer Critical Questions "Above the Fold": The very first screen a user sees must clearly and immediately answer: * What it is: A concise description of the product. * Who it's for: The specific target audience (e.g., solo founders, small teams). * Why it's different: Your unique value proposition (e.g., "open, composable, exportable code, agent workflow"). * Primary Action: A single, clear Call to Action (CTA) that aligns with the user's main goal. 2. Establish Credibility with Proof: Don't expect users to trust your claims. Show them proof early in the narrative. * Show, Don't Just Tell: The most powerful proof is a demo. Include a short (30-45s) silent video loop or a link to a real site built with the tool. * Use Social Proof: Before explaining "How it Works," insert tangible evidence like a customer logo, a compelling data point (e.g., "Used by 50+ teams"), or a strong user quote. 3. Define a Clear Call to Action (CTA): * Align CTA with the Audience: The primary CTA should be the main action you want your target user to take (e.g., "Generate My Site"). * Prioritize CTAs: Relegate secondary actions (like "See it on GitHub") to less prominent positions (tertiary buttons or footer links), especially for non-developer audiences. * Maintain a Persistent Mobile CTA: On mobile, a single primary CTA should always be visible. locale: en translateLanguages: - zh - zh-TW - ja pagesDir: .aigne/web-smith/pages sourcesPath: - ./assets/documents - ./README.md - ./aigne.yaml - ./assets/images - ./assets/recordings/README.md - ./CHANGELOG.md - ./agents defaultDatasources: - ./media.md media: minImageWidth: 600 lastGitHead: c4a4d3db4bf230e2c6873419e26b6654c39613a5 checkoutId: "" projectCover: .aigne/web-smith/cover.png shouldSyncAll: "" navigationType: "" appUrl: https://mhevtaeg.user.aigne.io ``` ## Summary Mastering the `config.yaml` file gives you full control over the website generation process. By carefully defining your project basics, site strategy, and data sources, you can guide the AI to produce a high-quality, relevant, and customized website. For more hands-on guidance, see the following guides: ::::card-group ::link-card{title="Create Website" description="Learn the complete workflow for generating your first site from scratch." icon="rocket" href="/en/docs/aigne-web-smith/guides-create-website-c47353/"} ::link-card{title="Prepare Materials" description="Understand how to prepare your source documents for the best results." icon="folder" href="/en/docs/aigne-web-smith/reference-prepare-materials-c47353/"} ::link-card{title="Troubleshooting" description="Find solutions to common configuration and generation issues." icon="wrench" href="/en/docs/aigne-web-smith/reference-trouble-shooting-c47353/"} :::: --- ## Prepare Materials URL: https://www.arcblock.io/en/docs/aigne-web-smith/reference-prepare-materials-c47353/ Great websites start before you run `aigne web generate`. This guide gives you a concrete checklist for collecting briefs, source docs, and proof so WebSmith can build pages that reflect your requirements, cite the right evidence, and require fewer revision cycles. ## The preparation workflow Here's how the process flows from gathering materials to getting your first website: ![Prepare Materials](https://media.arcblock.io/lib/84/8475404d894661cb.w1600.webp) Each step builds on the previous one. Better inputs mean better output—it's that simple. A well-organized content kit helps WebSmith create authoritative, on-brand pages from the start. ## Step 1. Start with the essentials Create a short brief that answers these four questions. A simple Markdown or Word doc works perfectly: | Question | Why it matters | Example | |---|---|---| | Audience | Tone, vocabulary, and proof should match who will read the page. | "Growth-stage fintech founders and their engineering leads." | | Problem | Forces clarity on the pain you solve. | "Manual onboarding creates 10+ hours of repetitive compliance reviews." | | Differentiator | Keeps the copy from sounding like every competitor. | "Only platform with KYC + KYB automation built on regional data lakes." | | Primary CTA | Aligns every section toward a single conversion action. | "Book a 20-minute integration review." | Save this file inside the project so you can add it to `sourcesPath`. ## Step 2. Gather your content and assets WebSmith works with what you give it. The more relevant material you provide, the better your website will be. Organize these items into a `sources` directory: ### Recommended content types | Content Type | Description | Example | |---|---|---| | Product Documents | Feature breakdowns, architecture notes, API references, pricing explanations. | `docs/product-overview.md`, `api/quickstart.md` | | Marketing Plans | Positioning, messaging house, campaign briefs, competitor summaries. | `marketing/positioning.pdf`, `brand/voice.md` | | Business Plans | Mission, vision, roadmap, funding milestones, leadership bios. | `company/mission.txt`, `investor/roadmap.pptx` | | Existing Content | Blog posts, FAQs, changelogs - anything that shows tone or repeatable stories. | `blog/*.md`, `faq.md`, `release-notes/2024-02.md` | | Media Files | Logos, product screenshots, team photos, charts. | `assets/logo.svg`, `screenshots/dashboard.png` | ### Supported formats | Category | Formats | |---|---| | Text | `.md`, `.txt`, `.html`, `.json`, `.yaml`, `.xml` | | Documents | `.pdf`, `.doc`, `.docx`, `.xls`, `.xlsx`, `.ppt`, `.pptx` | | Images | `.jpg`, `.jpeg`, `.png`, `.gif`, `.svg`, `.webp` | | Code | `.js`, `.ts`, `.py`, `.go`, `.rs`, `.java`, plus most other mainstream languages for snippet extraction | ## Step 3. Organize for clarity Group your files logically. This makes it easy for both you and WebSmith to find what's needed. **project-sources/** ```sh project-sources/ ├── 01_briefs/ │ ├── product-overview.md │ └── audience-matrix.md ├── 02_proof/ │ ├── testimonials.md │ └── security-metrics.xlsx ├── 03_assets/ │ ├── logo.svg │ └── dashboard.png └── 04_content/ ├── blog/ └── faq.md ``` Use descriptive folder names and prefixes. It should be obvious at a glance what each directory contains. ## Step 4. Connect your sources in config.yaml Point the `sourcesPath` array at the directories (or specific files) you just organized. This is the single most important configuration parameter. **config.yaml** ```yaml sourcesPath: - ./project-sources/01_briefs - ./project-sources/02_proof - ./project-sources/03_assets pagePurpose: - saas targetAudienceTypes: - businessOwners - developers rules: > Highlight 40% cost savings backed by customer quotes. Mention SOC 2 + ISO 27001. ``` When you run `aigne web generate`, WebSmith recursively reads those folders, chunks the files, and cites them while writing copy and assembling layouts. ## Choose your approach How much time do you have? Pick the approach that fits your situation. ### Quick start: Just need a demo? Perfect for when you need something up fast and can refine it later. - Start with a well-written README (~500+ words) and a few screenshots - Add them to `sourcesPath` - Run `aigne web generate`, review the result, and iterate once - Great for prototypes, internal demos, or testing the waters ### Recommended: Building something real This is the sweet spot for most teams launching a real product or service. 1. Document your audience, problem, differentiation, and CTA 2. Build a value matrix for each persona with functional + emotional proof 3. Outline each page section by intent before letting WebSmith write 4. Package testimonials, metrics, and screenshots as separate files 5. After generation, verify each section hits its goal, then refine and re-run ### Advanced: Team knowledge base For teams shipping multiple sites or maintaining long-term content systems. - Split your expertise into focused Markdown files organized by topic - Example structure: ```sh knowledge-base/ ├── foundation/ │ ├── mission.md │ └── brand-voice.md ├── products/ │ ├── payments-overview.md │ └── payments-technical-specs.md ├── proof-points/ │ ├── case-study-fintech-x.md │ └── g2-reviews.md └── audiences/ ├── developer-persona.md └── operator-persona.md ``` This approach scales beautifully: - Mix and match directories for different projects - Every site pulls from a single source of truth - Update one file (`case-study-fintech-x.md`) and it automatically improves every website that references it ## Quality checklist Before you run generate, make sure: - Every claim is backed by a data point, quote, or metric in your source files - Personas and CTAs are documented separately from marketing copy - Assets have descriptive names (`dashboard-dark.png`, not `image1.png`) - Sensitive or internal-only files are excluded (WebSmith reads everything you point to) - Source docs contain knowledge; style guidance goes in the `rules` field ## Tips for best results WebSmith is designed to generate great websites in one shot—but the quality depends on what you feed it. - Provide concrete details. The more specific your source materials (data points, quotes, metrics), the more authoritative your website will be. - Break content into focused files. Instead of one massive document, organize topics into smaller files. This helps WebSmith cite sources precisely and generate more structured content. - Separate content from instructions. Put your knowledge in source files, but keep layout and tone directives in the `rules` field where they belong. ## Next steps ::::card-group ::link-card{title="Getting Started" description="Install the AIGNE CLI, run `aigne web generate`, and review your first site." icon="rocket" href="/en/docs/aigne-web-smith/getting-started-c47353/"} ::link-card{title="Create Website" description="Learn every option available during the generate workflow." icon="wrench" href="/en/docs/aigne-web-smith/guides-create-website-c47353/"} ::link-card{title="Publish Website" description="Deploy to WebSmith Cloud or your own infrastructure once content looks great." icon="globe" href="/en/docs/aigne-web-smith/guides-publish-website-c47353/"} :::: --- ## Troubleshooting URL: https://www.arcblock.io/en/docs/aigne-web-smith/reference-trouble-shooting-c47353/ This guide helps you diagnose and fix common issues when working with AIGNE WebSmith. If you encounter problems during generation, publishing, or configuration, check the scenarios below for solutions. ## Configuration Issues ### Issue 1: Configuration file format error Error message: ``` Error: Failed to parse config file: Implicit map keys need to be followed by map values at line 112, column 1: lastGitHead: c4a4d3db4bf230e2c6873419e26b6654c39613a5 appUrl: https://staging.websmith.aigne.io ``` ``` Error: Failed to parse config file: Map keys must be unique at line 116, column 1: projectCover: .aigne/web-smith/cover.png appUrl: https://staging.websmith.aigne.io ^ ``` Possible causes: There's a YAML syntax error in your configuration file. Common issues include: - Using tabs instead of spaces for indentation - Using full-width colons (:) instead of ASCII colons (:) - Missing required quotes - Duplicate configuration items How to fix: 1. Check the line number mentioned in the error message to locate the issue 2. Verify the indentation on that line (use spaces, not tabs) 3. Make sure the colon is an ASCII colon (:), not a full-width colon (:) 4. Use an online YAML validator to check the syntax 5. Re-run `aigne web publish` after fixing > Tip: Except for configuration file format errors that need to be fixed, if some parameters are not configured correctly, the system will automatically use default values, which won't affect basic functionality. > ## Generation Issues ### Issue 2: Generated content doesn't match expectations You might encounter: - The tone of generated content doesn't match your requirements - The page structure doesn't match what you expected - Some important information is missing Possible causes: 1. The `rules` description in your config is insufficient or unclear 2. The `targetAudienceTypes` setting doesn't match your actual target audience 3. There are too few or irrelevant reference documents in `sourcesPath` How to fix: 1. Enrich `rules`: Add detailed guidance in your `config.yaml`: ```yaml rules: | ### Page Structure Requirements 1. Above the fold must include: * Clear product headline * Concise description * Primary call-to-action ### Content Tone - Use positive, confident language - Include concrete data and examples - Avoid marketing jargon ``` 2. Adjust audience: Ensure `targetAudienceTypes` matches your actual audience: ```yaml targetAudienceTypes: - customers # For end users - developers # For technical audience ``` 3. Add more sources: Include relevant documentation in `sourcesPath`: ```yaml sourcesPath: - ./README.md - ./docs - ./CHANGELOG.md ``` ### Issue 3: Images are low quality or missing You might encounter: - Low-resolution images in generated pages - Expected images not appearing Cause: The `media.minImageWidth` setting is too high, filtering out some images. How to fix: 1. Open the `config.yaml` file and find the `media` configuration: ```yaml media: minImageWidth: 800 # Current threshold ``` 2. Adjust this value based on your needs: 3. - 400-600: Will include more images, but some may be lower quality - 600-800: Balanced quality and quantity (recommended setting) - 800-1000: Only high-quality images are kept, quantity will be reduced 4. Run the update command after saving the file: ```bash aigne web update ``` ## Publishing Issues ### Issue 4: URL invalid error when publishing Error message: ``` Error: ⚠️ The provided URL is not a valid website on ArcBlock platform 💡 Solution: Start here to set up your own website to host pages: ``` Cause: The `appUrl` in your configuration is empty or points to an invalid website address. How to fix: Set the correct deployment address in `config.yaml`: ```yaml # Enter your website address appUrl: https://your-site.user.aigne.io # If you don't have a website yet, you can clear this configuration # appUrl: "" ``` ### Issue 5: Authorization expired error when publishing Error message: ``` ❌ Failed to publish pages: bundle: not authorized ``` Cause: Your login credentials have expired and need to be re-authorized. How to fix: Run the following commands in order: ```bash # First, clear old authorization information aigne web clear # Then republish, the system will prompt you to log in again aigne web publish ``` ## How to Recover ### Method 1: Restore using Git If you're using Git to manage your code, you can quickly restore to a previously working configuration: ```bash # Stash current changes git stash ``` Then regenerate the website: ```bash aigne web generate ``` > Tip: If you want to restore the stashed changes later, you can run `git stash pop` > ### Method 2: Clean and regenerate If you encounter issues that are hard to locate, you can clear all generated files and regenerate from scratch: ```bash # Clear all generated files, then regenerate aigne web clear && aigne web generate ``` > Note: This will delete all generated content, but won't affect your configuration files. After execution, the system will regenerate the website based on the current configuration. > ## Usage Tips Here are some practical tips to help you avoid common issues: ::::steps :::step{title="Save your change history:"} If you're using Git, remember to commit after each configuration file change, so you can easily go back to a previous version if something goes wrong ::: :::step{title="Back up before making changes:"} Before modifying important configurations, copy your configuration file as a backup, just in case ::: :::step{title="Test immediately after changes:"} After each configuration change, run `aigne web generate` right away to test, so you can catch any issues early ::: :::step{title="Check if the format is correct:"} After modifying YAML files, you can use online tools to check if there are any format errors ::: :::step{title="Start simple:"} Begin with the simplest configuration, and after confirming everything works, gradually add more complex features ::: :::step{title="Keep notes of your changes:"} Simply note down what you changed and why, so it's easier to find the cause when problems occur later ::: :::: ## Getting More Help If the methods above don't solve your problem, you can try: ::::steps :::step{title="Check configuration documentation:"} Review [Config Reference](/en/docs/aigne-web-smith/reference-config-c47353/) for detailed descriptions of each configuration item ::: :::step{title="Check command documentation:"} Refer to [Command Reference](/en/docs/aigne-web-smith/reference-command-c47353/) for detailed command usage ::: :::step{title="Check error logs:"} Carefully read the error messages displayed in the terminal, which usually contain specific hints ::: :::step{title="Use AIGNE Observability:"} Use the AIGNE Observability tool described below to get detailed execution records ::: :::step{title="Seek community help:"} Visit the [AIGNE Community](https://community.arcblock.io/discussions/boards/aigne) to ask questions, other users or developers may be able to help ::: :::: ## Using AIGNE Observability to Troubleshoot When you need to investigate complex issues in depth or report problems to the community, you can use AIGNE Observability. It records detailed execution processes for each step to help you or technical support staff quickly find issues. ### Start the Observability Server Run the following command to start the local observability server: **Start Observability Server** ```bash aigne observe ``` You'll see output showing: - Database path: where trace data is saved - Server address: open this address in your browser to view the observability dashboard ![Observability server running](https://media.arcblock.io/lib/e1/e10d985846bc2643.w1600.webp) ### View Execution Records 1. Open the dashboard: Click the server address shown in the output or open it in your browser 2. View operation records: The dashboard displays all WebSmith operations, including: 3. - Input and output data - Time taken for each step - Operation steps executed and their results - Detailed error information ![Observability dashboard showing execution records](https://media.arcblock.io/lib/5a/5a700be9522f2b53.w1600.webp) ### Report Issues with Observability When reporting problems to the community: 1. Capture the trace: Keep the observability server running during the problematic operation 2. Export the trace data: Export the relevant execution records from the dashboard 3. Report the issue: Visit the [AIGNE Community](https://community.arcblock.io/discussions/boards/aigne) and attach: 4. - Description of the problem - Steps to reproduce - Exported trace file - Your configuration (if relevant) > Tip: Trace records contain complete information about WebSmith's execution, including operations and results for each step. Providing this information to technical support or the community can greatly improve problem-solving efficiency. > --- ## Release Notes URL: https://www.arcblock.io/en/docs/aigne-web-smith/release-notes-c47353/ This document records all version updates for AIGNE WebSmith, including new features, bug fixes, and other changes, organized by version in reverse chronological order. ## [1.8.0-beta](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.7.0...v1.8.0-beta) (2025-11-13) ### Features - support for add-page and remove-page ([#231](https://github.com/AIGNE-io/aigne-web-smith/issues/231)) ([d02fe21](https://github.com/AIGNE-io/aigne-web-smith/commit/d02fe21b0425b870ad7ba98d4bc28c4a0f95c8e2)) ## [1.7.0](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.7.0-beta.3...v1.7.0) (2025-11-11) ## [1.7.0-beta.3](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.7.0-beta.2...v1.7.0-beta.3) (2025-11-11) ### Features - add automated section error fixing system with AI fallback ([#239](https://github.com/AIGNE-io/aigne-web-smith/issues/239)) ([7fe6421](https://github.com/AIGNE-io/aigne-web-smith/commit/7fe64215114d5cfa99afc658ec7f967855c1ed69)) - validate: enforce maximum length for project name and description ([#238](https://github.com/AIGNE-io/aigne-web-smith/issues/238)) ([3aef2d5](https://github.com/AIGNE-io/aigne-web-smith/commit/3aef2d556f2fdb40ef6ab4538bd7146e580fc5af)) ### Bug Fixes - improve error handling and parameter extraction in detail check utilities ([#240](https://github.com/AIGNE-io/aigne-web-smith/issues/240)) ([16f1397](https://github.com/AIGNE-io/aigne-web-smith/commit/16f1397809c47bbb73997cc08f026f3cebed476b)) - update chat model from aignehub/gemini-2.5-pro to google/gemini-2.5-pro ([0c01596](https://github.com/AIGNE-io/aigne-web-smith/commit/0c01596da4c6659ce6da080327d7ddf2bef5a650)) ## [1.7.0-beta.2](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.7.0-beta.1...v1.7.0-beta.2) (2025-11-10) ### Bug Fixes - tune naming for publish access token environment ([#234](https://github.com/AIGNE-io/aigne-web-smith/issues/234)) ([2887bd9](https://github.com/AIGNE-io/aigne-web-smith/commit/2887bd95487626ace7e4ecb200eb0c4222ab1ef8)) ## [1.7.0-beta.1](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.7.0-beta...v1.7.0-beta.1) (2025-11-10) ### Bug Fixes - add validation check for existing translation files ([#232](https://github.com/AIGNE-io/aigne-web-smith/issues/232)) ([f9760fb](https://github.com/AIGNE-io/aigne-web-smith/commit/f9760fbf295b51cf35a728e8a351f099401359bb)) ## [1.7.0-beta](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0...v1.7.0-beta) (2025-11-08) ### Features - upgrade to use the built-in components of version v2 ([#229](https://github.com/AIGNE-io/aigne-web-smith/issues/229)) ([93e3915](https://github.com/AIGNE-io/aigne-web-smith/commit/93e3915c6140c5b7061762cdc635a4632e92b3cf)) ## [1.6.0](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.15...v1.6.0) (2025-11-07) ## [1.6.0-beta.15](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.14...v1.6.0-beta.15) (2025-11-07) ### Bug Fixes - reload media after generated media ([#226](https://github.com/AIGNE-io/aigne-web-smith/issues/226)) ([1b0a62b](https://github.com/AIGNE-io/aigne-web-smith/commit/1b0a62b63eab6abf93950888346e9edc1a7d7952)) ## [1.6.0-beta.14](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.13...v1.6.0-beta.14) (2025-11-07) ### Features - add reasoning effort configuration for customizable AI model settings ([#223](https://github.com/AIGNE-io/aigne-web-smith/issues/223)) ([47813ce](https://github.com/AIGNE-io/aigne-web-smith/commit/47813ce77277ece9ec74a38870ae11d1540d7a6d)) - doc: update config doc and history entries for clarity and consistency ([#222](https://github.com/AIGNE-io/aigne-web-smith/issues/222)) ([1941dee](https://github.com/AIGNE-io/aigne-web-smith/commit/1941deed2f52edfbd84318ea546b92b771204e9d)) - guest: allow guests to publish web pages on the official site ([#220](https://github.com/AIGNE-io/aigne-web-smith/issues/220)) ([3367ce9](https://github.com/AIGNE-io/aigne-web-smith/commit/3367ce9e5dbff39afc879f5dc312cab6e9f93ce4)) ### Bug Fixes - centralize reasoning effort constants and refactor initialization logic ([#225](https://github.com/AIGNE-io/aigne-web-smith/issues/225)) ([fe3c0cb](https://github.com/AIGNE-io/aigne-web-smith/commit/fe3c0cbcabe80c75da3f309e954efc524bb8fb81)) - more accurate timing fields for pages ([#224](https://github.com/AIGNE-io/aigne-web-smith/issues/224)) ([bf074d9](https://github.com/AIGNE-io/aigne-web-smith/commit/bf074d9801d9c4fd15442c0f727416020c5d1d38)) ## [1.6.0-beta.13](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.12...v1.6.0-beta.13) (2025-11-05) ### Features - enhance page validation with media files and streamlined navigation ([#217](https://github.com/AIGNE-io/aigne-web-smith/issues/217)) ([7777805](https://github.com/AIGNE-io/aigne-web-smith/commit/77778050e4473222a859001c306265d22bc531ba)) - improve component loading with better error handling and filtering ([a375567](https://github.com/AIGNE-io/aigne-web-smith/commit/a375567cedf031f834712e133b66742c3d04df77)) ### Bug Fixes - improve error logging in choosePages ([#215](https://github.com/AIGNE-io/aigne-web-smith/issues/215)) ([645a591](https://github.com/AIGNE-io/aigne-web-smith/commit/645a591bea6434f0e1ad172c40e2aee82a07b503)) - make paid deployment more smooth stable ([#214](https://github.com/AIGNE-io/aigne-web-smith/issues/214)) ([d6bccfb](https://github.com/AIGNE-io/aigne-web-smith/commit/d6bccfb7a6a3d45c3498b4b84128a5ee62ac610e)) - tune theme/prefs/component/publish commands and validation ([#219](https://github.com/AIGNE-io/aigne-web-smith/issues/219)) ([d2e8465](https://github.com/AIGNE-io/aigne-web-smith/commit/d2e8465471cb2ff2bad4fc3deb8ad7e5245616d3)) ## [1.6.0-beta.12](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.11...v1.6.0-beta.12) (2025-11-05) ### Features - tune token consumption for update ops with intent analysis ([#212](https://github.com/AIGNE-io/aigne-web-smith/issues/212)) ([534aa3e](https://github.com/AIGNE-io/aigne-web-smith/commit/534aa3e3bce96feb7334e8d3701c7c29909a2059)) ## [1.6.0-beta.11](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.10...v1.6.0-beta.11) (2025-11-04) ### Features - add reasoning_effort parameter to agent configurations ([#184](https://github.com/AIGNE-io/aigne-web-smith/issues/184)) ([a31899f](https://github.com/AIGNE-io/aigne-web-smith/commit/a31899f805a9bd0fd5a75f90f02199d5298fb6ab)) - warn on invalid sources and tuning translate messages ([#183](https://github.com/AIGNE-io/aigne-web-smith/issues/183)) ([b99e0b5](https://github.com/AIGNE-io/aigne-web-smith/commit/b99e0b554a936da9466bd7eeab4e46e429cee977)) ## [1.6.0-beta.10](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.9...v1.6.0-beta.10) (2025-11-03) ### Features - doc: add config.yml guide and update latest update doc ([#175](https://github.com/AIGNE-io/aigne-web-smith/issues/175)) ([46b1ef0](https://github.com/AIGNE-io/aigne-web-smith/commit/46b1ef05282f9d345f5cd15b008eb6f8782f206c)) ## [1.6.0-beta.9](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.8...v1.6.0-beta.9) (2025-11-01) ### Bug Fixes - adjust component background colors ([#178](https://github.com/AIGNE-io/aigne-web-smith/issues/178)) ([6ce85f6](https://github.com/AIGNE-io/aigne-web-smith/commit/6ce85f63ae5833f0e027d5586d213d51264d84a4)) ## [1.6.0-beta.8](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.7...v1.6.0-beta.8) (2025-11-01) ### Features - support cleaning specific pages ([#179](https://github.com/AIGNE-io/aigne-web-smith/issues/179)) ([ec49d3f](https://github.com/AIGNE-io/aigne-web-smith/commit/ec49d3f157bd9dfea6268dd412442e8f21544468)) ## [1.6.0-beta.7](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.6...v1.6.0-beta.7) (2025-11-01) ### Bug Fixes - double slash in website structure display ([b905586](https://github.com/AIGNE-io/aigne-web-smith/commit/b905586d8b4c0c19964556b9fcbb1ba7ad2d8990)) ## [1.6.0-beta.6](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.5...v1.6.0-beta.6) (2025-11-01) ### Features - include page link when display site structure ([49569c8](https://github.com/AIGNE-io/aigne-web-smith/commit/49569c8fdd7fe0755df7ad63c20a73c4abf2f167)) ## [1.6.0-beta.5](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.4...v1.6.0-beta.5) (2025-10-31) ### Features - add carousel component ([#173](https://github.com/AIGNE-io/aigne-web-smith/issues/173)) ([d6c7a4b](https://github.com/AIGNE-io/aigne-web-smith/commit/d6c7a4b8308a406f44c0a43e05acbd458046fd31)) ## [1.6.0-beta.4](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.3...v1.6.0-beta.4) (2025-10-28) ### Bug Fixes - enhance multi-page content planning ([#168](https://github.com/AIGNE-io/aigne-web-smith/issues/168)) ([3106397](https://github.com/AIGNE-io/aigne-web-smith/commit/31063972134c1188fc17545fa7872de2ca3c1ce9)) ## [1.6.0-beta.3](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.6.0-beta.2...v1.6.0-beta.3) (2025-10-27) ### Bug Fixes - optimize built-in component styles ([#166](https://github.com/AIGNE-io/aigne-web-smith/issues/166)) ([e61bf64](https://github.com/AIGNE-io/aigne-web-smith/commit/e61bf643be8e0c48bc93d1520398f370fc36a825)) ## [1.6.0-beta.2](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.1-beta.2...v1.6.0-beta.2) (2025-10-26) ### Features - publish doc to official site ([#162](https://github.com/AIGNE-io/aigne-web-smith/issues/162)) ([11a7641](https://github.com/AIGNE-io/aigne-web-smith/commit/11a76414cd94383d2dc4a09466a98f3bd9159c9e)) ### Bug Fixes - remove source file change detection logic ([#165](https://github.com/AIGNE-io/aigne-web-smith/issues/165)) ([0408df8](https://github.com/AIGNE-io/aigne-web-smith/commit/0408df87d57ed771d2d2b592c9c52b9414ebd410)) ## [1.5.1-beta.2](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.1-beta.1...v1.5.1-beta.2) (2025-10-24) ### Bug Fixes - enhance content card components with screenshot display support ([#161](https://github.com/AIGNE-io/aigne-web-smith/issues/161)) ([1e4b67a](https://github.com/AIGNE-io/aigne-web-smith/commit/1e4b67a3593acda6b4682ddcaf0dfaa757348958)) ## [1.5.1-beta.1](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.1-beta...v1.5.1-beta.1) (2025-10-22) ### Bug Fixes - layout: adjust grid settings for mobile responsiveness ([#156](https://github.com/AIGNE-io/aigne-web-smith/issues/156)) ([b873dbc](https://github.com/AIGNE-io/aigne-web-smith/commit/b873dbc7db7bc41a875d9b9c691fe6d9e2d2f955)) ## [1.5.1-beta](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0...v1.5.1-beta) (2025-10-21) ### Bug Fixes - home page action link to auto ([0959250](https://github.com/AIGNE-io/aigne-web-smith/commit/0959250bd26ca368ccbedfcad98892ed6061bc4c)) - prevent duplicate tool calls in updatePageDetail ([#154](https://github.com/AIGNE-io/aigne-web-smith/issues/154)) ([ca5eba1](https://github.com/AIGNE-io/aigne-web-smith/commit/ca5eba14e72131db29c5ab0bf9c8deb27e4bd113)) ## [1.5.0](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.16...v1.5.0) (2025-10-19) ## [1.5.0-beta.16](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.15...v1.5.0-beta.16) (2025-10-17) ### Bug Fixes - doc review and update ([#147](https://github.com/AIGNE-io/aigne-web-smith/issues/147)) ([436344c](https://github.com/AIGNE-io/aigne-web-smith/commit/436344c1bd1f1ac4fa98200927e184d705061c7d)) - prevent component type changes in updateSection tool ([#151](https://github.com/AIGNE-io/aigne-web-smith/issues/151)) ([cdbdc91](https://github.com/AIGNE-io/aigne-web-smith/commit/cdbdc9126e64071e7ef40a78bcdfc6da436b71d1)) - tune resume capability and support navigation layout ([#150](https://github.com/AIGNE-io/aigne-web-smith/issues/150)) ([4c62fbd](https://github.com/AIGNE-io/aigne-web-smith/commit/4c62fbdbcb9bf441644d6a260a086d5481f1e46d)) ## [1.5.0-beta.15](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.14...v1.5.0-beta.15) (2025-10-16) ### Bug Fixes - reload translation model keys after refresh ([#146](https://github.com/AIGNE-io/aigne-web-smith/issues/146)) ([c0183ff](https://github.com/AIGNE-io/aigne-web-smith/commit/c0183ff3d1417a7a3c0970bb71e9a61f8b63dfa6)) ## [1.5.0-beta.14](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.13...v1.5.0-beta.14) (2025-10-16) ### Bug Fixes - tune translate doc improvement and translate output ([#144](https://github.com/AIGNE-io/aigne-web-smith/issues/144)) ([681b076](https://github.com/AIGNE-io/aigne-web-smith/commit/681b0769ea00db461439af0dd5b939ae42309952)) ## [1.5.0-beta.13](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.12...v1.5.0-beta.13) (2025-10-15) ### Bug Fixes - add terminal recording support ([#143](https://github.com/AIGNE-io/aigne-web-smith/issues/143)) ([f23fbab](https://github.com/AIGNE-io/aigne-web-smith/commit/f23fbab98129fba91200b798d317090dcb4175d2)) ## [1.5.0-beta.12](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.11...v1.5.0-beta.12) (2025-10-15) ### Bug Fixes - use better prompt structure for plan -> detail ([#141](https://github.com/AIGNE-io/aigne-web-smith/issues/141)) ([aa01994](https://github.com/AIGNE-io/aigne-web-smith/commit/aa019946cfac635c4a2f5acfffc4b1468b969adb)) ## [1.5.0-beta.11](https://github.com/AIGNE-io/aigne-web-smith/compare/v1.5.0-beta.10...v1.5.0-beta.11) (2025-10-16) ### Bug Fixes - Added project validation and dynamic slug handling for publishing ([#137](https://github.com/AIGNE-io/aigne-web-smith/issues/137)). - Enhanced error handling and structure validation ([#133](https://github.com/AIGNE-io/aigne-web-smith/issues/133)). - ux: Optimized visible copy for improved user interaction ([#136](https://github.com/AIGNE-io/aigne-web-smith/issues/136)). ... (older releases omitted for brevity) ... --- ## ARC CLI URL: https://www.arcblock.io/en/docs/arc-cli/ --- ## arc afs URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-afs/ `arc afs` is the command group for AFS file system operations. Every subcommand operates on an AFS path, a mounted location like `/src` or `/data`, not a raw filesystem path on your machine. Captured against `arc` `2.0.0-beta.50` (commit `a99fb2c37`, main, 2026-09-11). Run `arc --version` before you copy dumps; the commit is what pins the command surface. ```bash arc afs [options] ``` Run `arc afs --help` to see the full subcommand list. Every subcommand also accepts the global `--json`, `--view `, `--instance` / `-i`, and `--home ` flags described in [Overview](../overview/). `--yaml` was removed (never implemented); use `--json` or `--view json`. An unrecognized flag is now rejected (`Unknown argument: `, exit `5`), not silently ignored — for example `arc afs ls --bogus-flag foo` fails instead of running with `--bogus-flag` dropped. ## Which instance does this talk to `arc afs` needs a live instance to run against. With no flag it attaches to the **default** background instance (started with a bare `arc service start`); if none is running, every `arc afs` subcommand exits non-zero instead of silently falling back to a throwaway ad-hoc AFS: ```bash $ arc afs ls / ERROR: No AFS daemon is running for instance "default". Start it with: arc service start Or use --standalone for ad-hoc mode (no runtime state) ``` - **`--instance `** / **`-i`**: global. Attach to a named instance instead of the default one (see `arc service list`). Omit for `default` - **`--home `**: global. Instance root. Used by `arc service start` (create), `--standalone` (ad-hoc), and `arc did init`. To pick which instance, use `--instance`. If you pass both and they name different instances, the command fails - **`--standalone`**: force ad-hoc mode — load AFS straight from the local `.afs-config/config.toml` in the current directory instead of connecting to any running daemon. No runtime state (mounts you add elsewhere, live subscriptions, etc. are invisible); prints a `[standalone] not attached to any instance` line to stderr as a reminder ```bash arc service start --instance docs-demo --home ~/docs-demo # start a named instance once arc afs ls / --instance docs-demo # every later afs call names it explicitly ``` ## Reading and listing ### arc afs ls List directory contents. **Usage** ```bash arc afs ls [path] [options] ``` - `[path]` (optional, default `/`): the AFS path to list - **`--depth `**: maximum depth to list (default `1`) - **`-l`**: long listing format, shows kind and size - **`-R`**: list recursively - **`--limit `**: maximum number of entries to return - **`--max-children `**: maximum children per directory - **`--pattern `**: filter entries by glob pattern Aliased as `arc afs list`. `-R` and an explicit `--depth` are mutually exclusive — `-R` always lists at depth 10, so combining it with `--depth` is ambiguous about which one wins: ```bash $ arc afs ls /demo -R --depth 2 ERROR: ls: --depth conflicts with -R (recursive always lists at depth 10) — choose one: drop --depth to use -R's depth of 10, or drop -R and pass --depth explicitly ``` A path that does not exist exits `1` (not `0` with an empty list, and not `5`): ```bash $ arc afs ls /demo/does-not-exist ERROR: No data found for path: /demo/does-not-exist ``` **Example: recursive, long listing** ```bash arc afs ls /demo -l -R ``` ``` └── 📁 demo ├── 📄 notes.txt (fs:file) 15B └── 📁 reports (fs:directory) └── 📄 q1.txt (fs:file) 15B ``` ### arc afs read Read file content. **Usage** ```bash arc afs read [path] [options] ``` - `[path]` (positional, or **`--path `**, one of the two is required): path to read - **`--start-line `**: start line, 1-indexed, inclusive - **`--end-line `**: end line, 1-indexed, inclusive; `-1` for end of file Aliased as `arc afs cat`. **Example** ```bash $ arc afs read /demo/notes.txt Hello from AFS ``` A path that does not exist exits `1`: ```bash $ arc afs read /demo/does-not-exist.txt ERROR: No data found for path: /demo/does-not-exist.txt ``` ### arc afs stat Get file or directory info. **Usage** ```bash arc afs stat [path] ``` - `[path]` (positional, or **`--path `**, one of the two is required): path to inspect **Example** ```bash $ arc afs stat /demo/notes.txt PATH=/demo/notes.txt KIND=fs:file SIZE=15 MODIFIED=2026-08-01T04:00:51.508Z ``` A path that does not exist exits `1`, same message and exit code as `arc afs read`: ```bash $ arc afs stat /demo/does-not-exist.txt ERROR: No data found for path: /demo/does-not-exist.txt ``` ### arc afs search Search for content within an AFS path. **Usage** ```bash arc afs search [path] [query] ``` - `[path]` (positional, or **`--path `**, one of the two is required): path to search in - `[query]` (positional, or **`--query `**, one of the two is required): search query Aliased as `arc afs grep`. **Not** aliased as `find` — `find` was removed (it searches content, not names; to filter entries by name instead, use `arc afs ls --pattern`). **Example** ```bash $ arc afs search /demo revenue /demo/reports/q1.txt ``` ### arc afs explain Explain AFS concepts or paths. With no argument it prints a general overview (mount / path / uri concepts); with a topic or an actual AFS path it explains that specifically. **Usage** ```bash arc afs explain [topic] ``` - `[topic]`: a concept name (`mount`, `path`, `uri`) or an AFS path, e.g. `/src`. Can also be passed as **`--topic `** instead of positionally **Example** ```bash $ arc afs explain AFS Overview ============ AFS (Agentic File System) is a virtual filesystem that unifies different data sources into a single namespace. Core Concepts: - mount: Mount a data source to a virtual path - path: Virtual path, e.g., /src, /data - uri: Data source address, e.g., fs://, git://, sqlite:// Data Flow: User Path -> AFS -> /{mount} -> Provider -> Actual Data Examples: $ arc afs mount add /src fs:///path/to/source $ arc afs ls /src $ arc afs read /src/file.txt ``` ### arc afs subscribe Subscribe to AFS events under a path; prints one JSON event per line until you press Ctrl-C. Useful for watching a mount for changes made by another process (a build tool, another `arc afs write`, a running blocklet). **Usage** ```bash arc afs subscribe [path] [options] ``` - `[path]` (optional, default `/`): path prefix to watch, e.g. `/demo` or `/dev/code-agents`. Can also be passed as **`--path `** - **`--type `**: event type filter, e.g. `afs:write`, `afs:*` (default `afs:write`, wildcards allowed) **Example** (run in one terminal, then `arc afs write /demo/hello.txt ...` in another) ```bash $ arc afs subscribe /demo Subscribed to /demo (type=afs:write) — Ctrl-C to stop {"type":"afs:write","path":"/demo/hello.txt","source":"fs","timestamp":1787870798884} ``` ## Writing and deleting ### arc afs write Write content to a file. **Usage** ```bash arc afs write [path] [content] [options] ``` - `[path]` (positional, or **`--path `**, one of the two is required): path to write - **`--content `**: content to write - **`--mode `**: one of `replace` (default), `append`, `prepend`, `patch`, `create`, `update` - **`--patch `**: JSON array of patch operations, used with `--mode patch` - **`--meta `**: set a metadata field, repeatable - **`--if-match `**: optimistic-concurrency token from a prior `stat`/`read`/`write`. Rejects the write with `AFS_CONFLICT` if the current version differs; providers that don't support it ignore the flag (last-write-wins) **Example: write, then append** ```bash $ arc afs write /demo/draft.txt --content 'first draft' OK /demo/draft.txt $ arc afs write /demo/draft.txt --content ' plus more' --mode append OK /demo/draft.txt $ arc afs read /demo/draft.txt first draft plus more ``` ### arc afs delete Delete a file or directory. **Usage** ```bash arc afs delete [path] [options] ``` - `[path]` (positional, or **`--path `**, one of the two is required): path to delete - **`-r, --recursive`**: delete a directory recursively (default `false`) - **`--dry-run`**: print what would be deleted without deleting it - **`--yes`**: skip the TTY confirmation prompt (the prompt only appears when stdin is a real TTY; a non-interactive `arc afs delete` — a script, CI, this doc's own examples — never blocks on it either way) Aliased as `arc afs rm`. **Example: preview, then delete** ```bash $ arc afs delete /demo/draft.txt --dry-run Would delete /demo/draft.txt (dry-run) $ arc afs stat /demo/draft.txt PATH=/demo/draft.txt KIND=fs:file SIZE=21 $ arc afs delete /demo/draft.txt --yes OK /demo/draft.txt ``` ## Executing actions ### arc afs exec Execute an action exposed by a provider at a given path, for example a provider-defined operation that isn't just a plain file read/write. **Usage** ```bash arc afs exec [options] ``` - **`executable_path`** (required): the action path to execute - **`--args `**: JSON arguments, e.g. `--args '{"key": "value"}'` Not every mount exposes actions. Against a plain `fs://` mount attached to a running instance, calling an action path currently surfaces as a generic server error, not a specific one — the daemon's HTTP layer doesn't propagate the underlying AFS error text for this case: ```bash $ arc afs exec /demo/.actions/foo ERROR: Internal server error ``` In `--standalone` mode (no daemon in the loop) the same call gets the specific message instead: ```bash $ arc afs exec /demo/.actions/foo --standalone ERROR: No actions available for path: /.actions/foo ``` ## Mount management `arc afs mount` is its own subcommand group for managing what's mounted where. ```bash arc afs mount [options] ``` **`arc afs mount add` writes to the `.afs-config/config.toml` found by walking up from your current directory — not to any `--instance`/`--home` instance.** `--home` is rejected outright (exit `5`) because that flag would imply the change reaches an instance's daemon, and it never does. `--instance` / `-i` is the global instance selector: if that instance isn't running, the command fails before `mount add` runs. Drop `--home` and run from the right directory instead. To change what a running instance has mounted: `cd` into that instance's home directory (the one you passed to `arc service start --home`) before running `arc afs mount add`, then it takes effect for that instance immediately, no restart needed. (This is the mechanism behind the "`mount add` is not automatically an acceptance path" caveat on the [AFS runtime boundaries](../../afs/runtime-boundaries/) page — running `mount add` from the wrong directory is what makes the mount show up in `mount list` but not in `ls`.) ```bash $ arc afs mount add /demo fs:///path/to/a/local/directory --instance docs-demo ERROR: no instance named "docs-demo". `arc service list` shows 0 $ arc afs mount add /demo fs:///path/to/a/local/directory --home /Users/you ERROR: --home is not supported by `arc afs mount add`. `arc afs mount` only reads and writes the `.afs-config/config.toml` found by walking up from the current directory; it never reaches an instance's daemon, so the selected instance would silently not see the change. Drop the flag to edit the cwd config, or mount into a running instance at runtime with `arc attach --to --namespace --source `. ``` ```bash cd ~/docs-demo # the instance's --home directory arc afs mount add /demo fs:///path/to/a/local/directory arc afs ls /demo --instance docs-demo # visible right away ``` ### arc afs mount add Add a mount. **Usage** ```bash arc afs mount add [options] ``` - **`path`** (required): mount path, e.g. `/src` - **`uri`** (required): provider URI, e.g. `fs://./src` - **`--namespace `**: mount namespace - **`--description `**: mount description - **`--sensitive-args `**: field names to treat as sensitive credentials - **`-s, --set `**: set a credential directly, repeatable, bypasses the interactive prompt - **`--terminal`**: collect credentials via terminal readline instead of a browser - **`-f, --force`**: force re-collecting credentials, ignoring cached values **Example** ```bash $ arc afs mount add /demo fs:///path/to/a/local/directory Mounted fs:///path/to/a/local/directory at /demo ``` ### arc afs mount list List all mounts. **Usage** ```bash arc afs mount list [options] ``` Aliased as `arc afs mount ls`. There is no `--namespace` filter — the cwd `.afs-config/config.toml` is one table with no per-namespace slice to filter by, so passing `--namespace` is rejected: ```bash $ arc afs mount list --namespace anything ERROR: --namespace is not supported by `arc afs mount list`. `arc afs mount` reads and writes the cwd `.afs-config/config.toml` as one table; there is no per-namespace slice. Drop --namespace. ``` **Example** (one entry shown; your actual list will contain every mount you've added) ```bash $ arc afs mount list /demo -> fs:///path/to/a/local/directory ``` ### arc afs mount remove Unmount a path. **Usage** ```bash arc afs mount remove [options] ``` - **`path`** (required, **positional only**): mount path to remove. `--help` also lists a `--path` option marked `[required]`, but passing it as a flag instead of positionally does not satisfy the requirement — it still fails with `Not enough non-option arguments: got 0, need at least 1`. Always pass the path positionally - **`--namespace `**: not supported — `arc afs mount` treats the cwd `.afs-config/config.toml` as one table with no per-namespace slice, so `remove --namespace foo` is rejected (`ERROR: --namespace is not supported by 'arc afs mount remove'`), same as on `mount list` Aliased as `arc afs mount rm`. **Example** ```bash $ arc afs mount remove /demo Unmounted /demo ``` Passing the path as `--path` instead of positionally does not work, even though `--help` lists it as a required option: ```bash $ arc afs mount remove --path /demo ERROR: Not enough non-option arguments: got 0, need at least 1 ``` ### arc afs mount validate Validate the current mount configuration. **Usage** ```bash arc afs mount validate ``` **Example** ```bash $ arc afs mount validate Configuration is valid ``` ## Notes on output When an `afs` command talks to a running instance — the default — it writes nothing to stderr at all: the result on stdout is the whole output. Boot logging belongs to the daemon, not to your shell. `--standalone` is the exception, because there the command boots AFS inside your own process and that boot log goes to your terminal. Three lines are invariant — the one naming the ad-hoc mode, one echoing which `.afs-config/config.toml` file(s) it read, and, whenever `AFS_DID_SPACE_SCOPE_SECRET` is unset, a `warn` record from `node:boot` reporting that DID Space scope de-identification is off and directory names are stored in plaintext: ```text [standalone] not attached to any instance — ad-hoc mode (no runtime state) [standalone] config: /path/to/.afs-config/config.toml {"ts":"…","level":"warn","service":"arc-node","ns":"node:boot","message":"[afs-loader] AFS_DID_SPACE_SCOPE_SECRET unset — DID Space scope de-identification is OFF (plaintext directories). Set the secret to enable; set AFS_DID_SPACE_REQUIRE_DEID=true to enforce."} ``` Set the secret and the third line is gone; set `AFS_DID_SPACE_REQUIRE_DEID=true` to make its absence an error instead. Anything further on stderr is `node:boot` reporting on your own machine — a mount it could not establish, or a `[code-agents] recover ok: ...` line from the scheduler's own boot, say — so the total line count differs between hosts. Recognise the three above rather than counting them. None of it is part of the command's result, and all of it is omitted from the examples above. --- ## arc attach URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-attach/ `arc attach` reverse-mounts a local directory into a *remote* arc daemon, exposing it as a provider under `/modules/{namespace}` on that remote daemon. This is the opposite direction from `arc afs mount`: instead of mounting something remote into your local AFS, you're making something local visible to a remote AFS. **Usage** ```bash arc attach --to [options] ``` `--to` is the only strictly required flag; what else you need depends on which of the three things you're attaching: - **directory attach** (the default): `--namespace ` + `--source ` — exposes a local directory as a provider mounted at `/modules/{namespace}` on the remote - **host attach**: `--as-host` — exports this host's HostFace at `/peers/{peer.json.id}` on the remote (no `--namespace`/`--source` needed) - **engine attach**: `--as-engine ` alone — attaches a bare code-agents engine under that id; combined with `--as-host` it's just display metadata alongside the HostFace **Options** - **`--to `** (required): target daemon URL, e.g. `ws://host:4900` or `ws://host:4900/ws/attach` - **`--namespace `**: namespace to expose on the target, mounted at `/modules/{namespace}` (directory attach) - **`--source `**: local directory to expose as the provider (directory attach) - **`--as-engine `**: engine id alone; with `--as-host` it's display metadata only (remote id is `peer.json`'s `id`) - **`--as-host`**: export this host's HostFace at `/peers/{peer.json.id}` on the target - **`--readonly`**: expose the source as read-only (directory attach) - **`--replace`**: replace an existing session at this namespace - **`--token `**: owner access token for a remote daemon (skipped for loopback targets) - **`--browser`**: open a browser for the auth flow (default `true`); pass **`--no-browser`** with `--token` for unattended runs - **`--json`**: print machine-readable events on stdout instead of the default human text - **`--view`**: output view format (`json` is equivalent to `--json`) - **`--instance `** / **`-i`**: which local ARC instance this command operates against; omit for `default` - **`--home `**: instance root (where this host's `peer.json` and credentials live; usually not needed). To pick which instance, use `--instance` On SIGINT (Ctrl+C) `arc attach` detaches gracefully so the remote side unmounts cleanly. **Example** ```bash arc attach --to ws://host:4900 --namespace my-local-src --source ./src --readonly arc attach --to ws://host:4900 --as-host ``` ### `--json` With `--json`, every progress line (`Attaching...`, `to:`, `namespace:`, `source:`, `Press Ctrl+C to detach.`, `Detaching...`) moves to stderr, and stdout carries only newline-delimited JSON events — a script piping `arc attach ... --json` can read stdout as pure JSON without filtering out human prose: ```bash $ arc attach --to ws://127.0.0.1:PORT/ws/attach --source /tmp --namespace test --json ``` stdout (only this one line, on a successful attach): ```json {"event":"attached","sessionId":"sess_test_...","namespace":"test","targetPath":"/modules/test"} ``` stderr (all progress, banner omitted): ``` Attaching... to: ws://127.0.0.1:PORT/ws/attach namespace: test source: /tmp Press Ctrl+C to detach. ``` On a failure, `--json` does not add a matching JSON object to stdout — stdout stays empty and the error is still the human `ERROR: ...` line on stderr, for both a validation failure (missing required combination) and a connection failure, exit `5` either way: ```bash $ arc attach --to ws://127.0.0.1:1/ws/attach --source /tmp --json ``` stdout: (empty) stderr: ``` ERROR: attach requires --namespace and --source, or --as-engine, or --as-host ``` ```bash $ arc attach --to ws://127.0.0.1:9/ws/attach --namespace test --source /tmp --json ``` stdout: (empty) stderr: ``` Attaching... to: ws://127.0.0.1:9/ws/attach namespace: test source: /tmp ERROR: attach failed [cockpit-unreachable]: connect ECONNREFUSED 127.0.0.1:9 ``` --- ## arc blocklet URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-blocklet/ `arc blocklet` covers a blocklet's whole lifecycle: scaffolding a new package, building it, validating it, and deploying it, either on its own or as part of a fleet. Captured against `arc` `2.0.0-beta.50` (commit `a99fb2c37`, main, 2026-09-11). Run `arc --version` before you copy dumps; the commit is what pins the command surface. ```bash arc blocklet [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). ## Scaffold ### arc blocklet create Scaffold a new blocklet package. Aliased as `arc blocklet init` (kept for backwards compatibility). **Usage** ```bash arc blocklet create [dir] [options] ``` - `[dir]` (optional, default cwd): blocklet directory - **`--name `**: blocklet name (default: directory name) - **`--recipe `** (alias `--template`): scaffold recipe, one of `basic`, `blank`, `blog`, `agent`, `minimal-app`, `agent-workspace`, `support-community` (default `basic`) `--name` must derive a legal blocklet identifier — checked, and rejected, *before* anything is written to disk: ```bash $ arc blocklet create bad-dir --name "Not A Valid Name!" ERROR: Error: Cannot derive a blocklet DID from --name "Not A Valid Name!": a blocklet identifier allows alphanumeric, hyphen, underscore only. Pass a valid identifier instead, e.g. --name Not-A-Valid-Name. ``` No `bad-dir` directory gets created. A valid name scaffolds normally, and prints a `Next:` hint for the next step in the pipeline: ```bash $ arc blocklet create my-app --recipe basic Created blocklet.yaml with did: "did:blocklet:my-app" Next: arc blocklet build /path/to/my-app ``` The `Next:` chain follows the recipe's own capabilities: a DSL-bearing recipe (`minimal-app`, `agent-workspace`, `support-community`, `agent`, `blog`) inserts `arc dsl validate` before the build step, a manifest-only recipe (`basic`, `blank`) does not: ```bash $ arc blocklet create my-agent --recipe minimal-app Created minimal app blocklet "my-agent" with 18 file(s). Next: arc dsl validate /path/to/my-agent $ arc dsl validate /path/to/my-agent Passed DSL validation path: /path/to/my-agent files: 16 Next: arc blocklet build /path/to/my-agent $ arc blocklet build /path/to/my-agent Published 20 file(s) → /path/to/my-agent/dist .afs/manifest.json (http-mount protocol) blocklet.dist.json (flat manifest) instance: requires /instance DID Space Next: arc blocklet run /path/to/my-agent Deploy to CF Pages: arc blocklet deploy /path/to/my-agent --project ``` The `Next:` hint after a DSL-bearing scaffold is `arc dsl validate`, and that command does exit 0 on a fresh `minimal-app`. The rest of the DSL check chain is not uniformly green. With zero edits after `arc blocklet create . --recipe minimal-app`: ```bash $ arc dsl lint . Passed DSL lint path: /path/to/my-agent files: 16 $ arc dsl format --check . Would format 0 file(s) (dry-run) — nothing to change path: /path/to/my-agent files: 5 $ arc dsl generate --check . ERROR: Failed DSL generate (dry-run) — would change 4 file(s) path: /path/to/my-agent files: 11 changed: .aup/app.json, .aup/pages/agent.json, .aup/pages/home.json, .aup/wrapper.json WARNING missing_man_coverage .aup/man/home.yaml: page "home" declares node-bound action(s) but has no .aup/man/home.yaml coverage ERROR generated_changed .aup/app.json: Generated artifact is stale. Run arc dsl generate --write. ERROR generated_changed .aup/pages/agent.json: Generated artifact is stale. Run arc dsl generate --write. ERROR generated_changed .aup/pages/home.json: Generated artifact is stale. Run arc dsl generate --write. ERROR generated_changed .aup/wrapper.json: Generated artifact is stale. Run arc dsl generate --write. $ arc dsl doctor . ERROR: Failed DSL doctor path: /path/to/my-agent decompile step: failed (0 files, 0 changed) ``` `lint` and `format --check` exit 0; `generate --check` and `doctor` currently exit 5. This is the CLI's current behavior on a zero-edit scaffold, not a documentation workaround — do not treat those two gates as green just because `validate` passed. ### arc blocklet recipe Discover the available scaffold recipes. ```bash arc blocklet recipe ``` - **`arc blocklet recipe list`**: list scaffold recipes - **`arc blocklet recipe explain `**: explain one recipe **Example** ```bash $ arc blocklet recipe list Blocklet scaffold recipes: basic Create only a blocklet manifest. capabilities: manifest generated files: 1 ... minimal-app Create a tiny complete app with one web page, one AUP app, one agent, and generated settings. capabilities: web, aup, agent, settings generated files: 18 source files: 14 ... $ arc blocklet recipe explain basic Recipe: basic Create only a blocklet manifest. capabilities: manifest generated files: blocklet.yaml AFS data: blocklet.yaml checks: arc blocklet check ``` ## Build and validate This repo's own build-and-check pattern (`bun .claude/verify/config.ts`) is `arc blocklet check` then `arc blocklet build`, run against `blocklets/arcblock`. ### arc blocklet build Build a Pages-ready `dist/`, copies files and writes `.afs/manifest.json` plus a flat manifest. **Usage** ```bash arc blocklet build [dir] [options] ``` - `[dir]` (optional, default cwd): blocklet directory - **`--output `**: output directory (default `/dist`) - **`--dry-run`**: compute the manifest without copying files or writing to disk - **`--clean`**: clean the output directory before writing (default `true`) On success it also prints a `Next: arc blocklet run ` hint plus a `Deploy to CF Pages:` hint — see the full chain under [arc blocklet create](#arc-blocklet-create) above. ### arc blocklet check Validate a blocklet against a recipe/profile contract. Aliased as `arc blocklet validate`. **Usage** ```bash arc blocklet check [dir] [options] ``` - `[dir]` (optional, default cwd): blocklet directory - **`--profile `**: validation profile, one of `basic`, `minimal-app`, `agent-workspace`, `support-community` (default `basic`) Unlike `create` and `build`, `check` does not print a `Next:` hint on success. ### arc blocklet dev Scan blocklet directory conventions and report the results, a lint pass over the directory shape rather than the DSL content (that's `arc dsl lint`). ```bash arc blocklet dev [dir] ``` ## Inspect ### arc blocklet list List local blocklet packages: discovers `blocklet.yaml`, reports publish status. ```bash arc blocklet list [dir] ``` ### arc blocklet inspect Show the manifest and file list for a local blocklet package. ```bash arc blocklet inspect ``` - **`ref`** (required): path to a blocklet directory ## Run and deploy ### arc blocklet run Serve a single blocklet on the daemon and print its access URLs. **Usage** ```bash arc blocklet run [options] ``` - **`path`** (required): path to the blocklet directory to serve To keep a source across daemon restarts, record it on a named instance: `arc service start --instance --blocklet `. See [arc service](../command-reference-service/). ### arc blocklet deploy Publish a blocklet locally, then deploy it to Cloudflare Pages, in one step. **Usage** ```bash arc blocklet deploy [dir] [options] ``` - `[dir]` (optional, default cwd): blocklet directory - **`--project `**: Pages project name (default: blocklet id); multiple blocklets deployed to the same project share a single aggregated http-mount tree - **`--domain `**: domain to bind the instance to - **`--cloud `**: `cf` pushes to Cloudflare Pages, `none` is staging only (default `cf`) - **`--branch `**: git branch label for the deploy (default `main`) - **`--staging-root `**: staging dir root (default `~/.afs/blocklets-staging`) - **`--cf-account-id `** / **`--cf-api-token `**: forwarded to wrangler - **`--verify`**: after `--cloud=cf` with `--domain`, verify the package, diagnostics, and live routes (default `true`) - **`--routes `**: space/comma-separated live routes to verify (default `/`) - **`--compare-local`**: also fetch matching local routes and compare status/health - **`--local-port `**: local Arc port used with `--compare-local` (omit to use the instance registry) - **`--timeout-ms `**: per-request verification timeout in milliseconds (default `10000`) ### arc blocklet instance Manage blocklet instances, i.e. deployments. ```bash arc blocklet instance [options] ``` - **`arc blocklet instance deploy `**: deploy a published `dist/` to local Pages and bind a domain. `--cloud ` picks the target (default `fs`); `--pages-root ` sets the local Pages store root for `--cloud=fs` (default `~/.arc/pages`) - **`arc blocklet instance list`**: list deployed instances, i.e. Pages projects - **`arc blocklet instance inspect `**: show details for a deployed instance - **`arc blocklet instance destroy `**: tear down a deployed instance, removes all deployments and domains; requires `--force` to confirm - **`arc blocklet instance logs `**: show deploy history for a Pages instance (no runtime logs available — Pages has no runtime log stream). `--follow` was removed (it used to be accepted and immediately error "not supported"; now it's rejected outright as an unknown argument, exit `5`) ## Fleet `arc blocklet fleet` deploys a group of blocklets as one aggregate Pages project, this is how a multi-domain site fleet (like this one) gets deployed together. ```bash arc blocklet fleet [dir] [options] ``` Shared options across the fleet subcommands: `--blocklets ` (overrides `--fleet`), `--fleet ` (defaults to `/site-fleet.yaml` or `/fleet.yaml`), `--deployment ` (resolves the fleet manifest path from `instances.json`, mutually exclusive with `--fleet`), `--project ` (default `afsd-blocklets`), `--domain-root ` (default `afsd.io`). `--deployment`/`--fleet` is a declared, enforced conflict on all four subcommands (not just prose): ```bash $ arc blocklet fleet deploy --deployment foo --fleet bar.yaml ERROR: Arguments deployment and fleet are mutually exclusive ... ``` Passing only one of the two flags clears this specific check — it then fails later for a different, expected reason (no such fleet manifest here), which is how you tell the guard discriminates rather than rejecting everything: ```bash $ arc blocklet fleet deploy --fleet bar.yaml ERROR: Error: Fleet manifest not found: /path/to/bar.yaml ``` - **`arc blocklet fleet deploy [dir]`**: publish and deploy multiple blocklets with aliases, Web Provider assets, and smoke checks. `--publish` runs `arc blocklet build` for every blocklet before staging (default `true`); `--web-library` stages Web Provider themes/widgets into `/web/.library` (default `true`); `--web-library-dir ` picks the Web Provider package dir to stage from (default `providers/runtime/web-device`) - **`arc blocklet fleet verify [dir]`**: verify a deployed fleet without publishing or pushing changes - **`arc blocklet fleet doctor [dir]`**: check local prerequisites for a fleet deploy (wrangler availability when `--cloud cf`, staging root, etc.) - **`arc blocklet fleet rollback [dir]`**: roll a Cloudflare Pages fleet project back to a previous deployment --- ## arc collections URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-collections/ `arc collections` is a small authoring-tool group for the `collections:` declarations in a blocklet's `blocklet.yaml` — the block that tells the runtime which `content/` subtrees are indexable collections, and what faces (web, sitemap, llms) they expose. Right now it has one subcommand. ```bash arc collections [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). ### arc collections scan Scan a site's `content/` directory and emit a `collections:` YAML fragment you can paste into `blocklet.yaml`, instead of hand-writing the declaration. **Usage** ```bash arc collections scan [dir] [options] ``` - `[dir]` (optional, default `.`): site root — the directory that contains `content/` **Example** (run from a site root with a `content/` tree; two of the emitted collections shown, the rest follow the same shape) ```bash $ arc collections scan . # Paste into blocklet.yaml. mcp is intentionally omitted — opt-in only (epic #3657 W2). collections: articles: type: local:articles indexable: - "content/articles/**/content.md" faces: web: true sitemap: true llms: [index, full] docs: type: local:docs indexable: - "content/docs/**/content.md" faces: web: true sitemap: true llms: [index, full] ... ``` Paste the emitted fragment into the target `blocklet.yaml`'s `collections:` key; `arc collections scan` only prints it, it does not write the file for you. --- ## arc completion URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-completion/ `arc completion` generates a tab-completion script for your shell and prints it to stdout. It never writes anywhere on disk — turning the output into a file, or appending it to your shell's startup file, is a step you do yourself. Captured against `arc` `2.0.0-beta.48` (commit `5a5316bde`, main, 2026-09-10). Run `arc --version` before copying anything below; the generated script can change between builds. ## Usage ```bash arc completion [shell] ``` - **`shell`**: `bash`, `zsh`, or `fish`. Omit it and `arc` detects your shell from `$SHELL`; if `$SHELL` is unset, or set to something that isn't one of those three, it falls back to `bash`: ```bash $ env -i PATH="$PATH" SHELL=/bin/zsh arc completion | head -1 #compdef arc $ env -i PATH="$PATH" SHELL=/usr/bin/tcsh arc completion | head -1 ###-begin-arc-completions-### ``` ## Generating a script The three scripts are different lengths — bash has to do the matching and escaping itself, zsh hands most of that to `_describe`, and fish is a single `complete` call: ```bash $ arc completion bash | wc -l 86 $ arc completion zsh | wc -l 67 $ arc completion fish | wc -l 14 ``` A shell name outside the three choices is rejected the same way any other invalid choice value is — a yargs validation error, exit `5`: ```bash $ arc completion nosuchshell ERROR: Invalid values: Argument: shell, Given: "nosuchshell", Choices: "bash", "zsh", "fish" ``` (trimmed here — the rest of the block is the same text `arc completion --help` prints) ## Installing it Each script's own header states how it expects to be installed. `arc completion ` only prints; it never writes to any of the paths below for you. ### bash ```bash arc completion bash >> ~/.bashrc ``` Use `~/.bash_profile` instead on macOS, per the comment inside the script. Open a new shell, or `source` the file, to pick it up. ### zsh ```bash arc completion zsh >> ~/.zshrc ``` If your `~/.zshrc` has never run `compinit`, the script bootstraps it the first time it loads, so you don't add that step separately. It also re-registers itself on every prompt, so a later `compinit` elsewhere in your setup that rebuilds the completion table doesn't silently drop `arc`'s entry. ### fish ```bash mkdir -p ~/.config/fish/completions arc completion fish > ~/.config/fish/completions/arc.fish ``` The `mkdir -p` matters — `>` does not create the parent directory, and fish only picks up completion files that are already inside `~/.config/fish/completions/`. ## What it completes Press Tab after any of these and the installed script asks the running `arc` binary what fits, so the answer always matches the binary you actually have, not a snapshot baked in when the script was generated: - **Command names** — `arc d` offers `did`, `deploy`, `drain`, `dsl` - **Subcommand names** — `arc did ` offers `init`, `check`, `issue`, `verify`, `info`, `list`, `issuer` - **`--instance` / `-i` values** — the same names `arc service list` would show, so `arc service status -i ` only ever offers an instance you actually have - **`--recipe` / `--template` values** — `arc blocklet create --recipe ` offers the same choices `arc blocklet create --help` lists: `basic`, `blank`, `blog`, `agent`, `minimal-app`, `agent-workspace`, `support-community` Anything else — an AFS path in `arc afs ls `, for example — is not one of the slots above, so the script falls through to your shell's ordinary filename completion instead. ## How values reach your command line Instance names and recipe names are not fixed at generation time. Each keystroke queries the arc binary you have installed right now, so a script you generated last week still offers an instance you created five minutes ago. Insertion is also safe regardless of what characters a value contains. bash quotes every candidate with `printf %q` before inserting it, so an instance literally named `my prod box` completes to the three-word-safe `my\ prod\ box` instead of splitting into separate words, and a name containing shell metacharacters is never handed to the shell unescaped. zsh's `_describe` carries the same property built in. ## Exit codes | What you ran | Exit code | | --- | --- | | `arc completion bash` / `zsh` / `fish` | `0` | | `arc completion` (no argument, shell detected) | `0` | | `arc completion ` | `5` | --- ## arc deploy URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-deploy/ `arc deploy` deploys and manages blocklets, both local daemon registration (for development) and DID Space publishing (for real distribution). This is a different thing from `arc blocklet deploy`, which pushes to Cloudflare Pages, `arc deploy` is about the local daemon and DID Space. ```bash arc deploy [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). - **`path`**: local blocklet directory path, a `git+https://…` URL, or an `https://…/archive.tar.gz` URL — the latter two (remote sources) additionally require `--publish`, or the command fails fast with `Remote sources (git+url / http-url) require --publish.` **Options** - **`--publish`**: publish blocklet code to the local developer DID Space instead of registering with the local daemon (zero network/auth); only local publishes are visible to `arc deploy show`/`list --published` - **`--server `**: publish to a *remote* DID Space server instead of the local one, implies `--publish`; always requires auth (browser flow, cached credential, or `--token`), even against a loopback URL - **`--token `**: bearer token for `--server`, otherwise an interactive browser auth flow is used. Declared and enforced: passing `--token` without `--server` fails fast rather than silently ignoring the token — ```bash $ arc deploy /path/to/my-blocklet --token abc123 ERROR: Missing dependent arguments: token -> server ``` Passing both together clears that check and moves on to the real work — it fails here only because the path doesn't exist, proving the check discriminates rather than rejecting everything: ```bash $ arc deploy /path/to/my-blocklet --server http://127.0.0.1:9 --token abc123 --no-browser ERROR: Error: No blocklet found at /path/to/my-blocklet. Expected a directory with blocklet.yaml, .aup/, index.html, or a terminal index file. ``` - **`--browser`**: open a browser for the auth flow when publishing to `--server` (default `true`); pass **`--no-browser`** with `--token` for unattended runs - **`--prerender`**: pre-render web pages into `.web-cache/` before publishing, same as `arc blocklet build`'s `ARC_PRERENDER`; on by default, pass `--no-prerender` or `ARC_PRERENDER=0` to opt out - **`--dry-run`**: print the deploy plan without registering, publishing, or fetching `arc deploy ` on its own registers and serves the blocklet for the current daemon session only — it does not survive a restart. There is no `--persist` flag on `arc deploy` itself; to make a blocklet source come back after `arc service restart`, record it on the instance instead: ```bash arc service start --blocklet /path/to/my-blocklet # or: arc service restart --blocklet /path/to/my-blocklet ``` **Examples** (from `arc deploy --help`) ```bash arc deploy /path/to/my-blocklet # register and serve a local blocklet (hot-adds if the instance is running) arc deploy /path/to/my-blocklet --dry-run # preview a deploy without writing arc service start --blocklet /path/to/my-blocklet # record the source on the instance so it survives restart arc deploy /path/to/my-blocklet --publish # publish blocklet code to developer DID Space arc deploy list # list the default instance's registered blocklet sources arc deploy list -i alice # list only instance alice's registered sources arc deploy list --home /path/to/instance # list sources of the instance registered at that home arc deploy list --published # list blocklets published to DID Space arc deploy show did:blocklet:z2x # read back files published to DID Space arc deploy remove /path/to/my-blocklet # drop a source from the instance record; restart to apply ``` ### arc deploy list List all extra-registered blocklet sources, or published DID Space blocklets. **Usage** ```bash arc deploy list [options] ``` - **`--published`**: list blocklets published to DID Space (`blocklet-sources.json`), instead of registered sources **Example** ```bash $ arc deploy list Registered blocklet sources (via instance default): No extra blocklet sources registered. Tip: arc service start --blocklet ``` ### arc deploy remove Drop one registered extra blocklet source from the instance record (arc#6061; not a hot-unplug — restart to apply). **Usage** ```bash arc deploy remove [options] ``` - **`target`** (required): blocklet dir, or its parent extra-source dir, to drop **Example** (accept path: `target` is actually registered) ```bash $ arc deploy remove /path/to/my-blocklet Unregistered /path/to/my-blocklet from instance default. Restart with `arc service restart` to apply. ``` Nothing registered to drop is a reject path, exit `1`: ```bash $ arc deploy remove /path/to/my-blocklet ERROR: Error: "/path/to/my-blocklet" is not a registered extra source on instance default. Registered: (none) ``` ### arc deploy show Read back the files published to the developer DID Space for a blocklet. **Usage** ```bash arc deploy show [subpath] [options] ``` - **`did`** (required): blocklet DID, or bare id, to inspect - **`subpath`**: optional path inside the published tree --- ## arc did URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-did/ `arc did` manages identity and trust: generating a DID identity for yourself, a provider, or a blocklet; issuing and verifying verifiable credentials; and managing the list of issuers you trust. Captured against `arc` `2.0.0-beta.50` (commit `a99fb2c37`, main, 2026-09-11). Run `arc --version` before you copy dumps; the commit is what pins the command surface. ```bash arc did [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). `arc did init --home` is one of the places `--home` creates identity at a chosen root. ## Identity ### arc did init Generate a DID identity. **Usage** ```bash arc did init [options] ``` - **`--developer`**: generate a developer root key (`ROLE_ACCOUNT`) - **`--provider`**: derive a provider DID from the developer key (`ROLE_PROVIDER`) - **`--blocklet`**: derive a blocklet DID from the developer key (`ROLE_BLOCKLET`) - **`--force`**: overwrite an existing identity Without any of `--developer`/`--provider`/`--blocklet`, it auto-detects which kind to generate based on where you run it. ### arc did info Show identity and credential info. ```bash arc did info ``` **Example** (run outside a recognized project) ```bash $ arc did info ERROR: No entity manifest found in current directory (looked for blocklet.yaml, .aup/, index.html, index.{txt,md,ans}, package.json) ``` **Example** (run inside a project that has an identity and an issued credential) ```bash $ arc did info acme-widget DID=z2qaHJMfMAjP3t1eooziSUa6n7v25AbyfH4G1 CREDENTIAL=true ISSUER=z2qaHJMfMAjP3t1eooziSUa6n7v25AbyfH4G1 ``` ### arc did check Run conformance tests for the current provider. ```bash arc did check ``` ### arc did list List identities stored in this instance home — reads whatever identity files are on disk; no running daemon is required. Captured against `arc` `2.0.0-beta.48` (commit `5a5316bde`, main, 2026-09-10). ```bash arc did list [options] ``` **Example** (fresh home, nothing generated yet) ```bash $ arc did list --home /tmp/arc-did-doc-home No identities ``` **Example** (after `arc did init --developer`) ```bash $ arc did init --developer --home /tmp/arc-did-doc-home CREATED developer:developer DID=z1kExiHjGkUcBe6YTpyspLLNy1wb2vfCsV2 Next: arc did list --home /tmp/arc-did-doc-home $ arc did list --home /tmp/arc-did-doc-home developer DID=z1kExiHjGkUcBe6YTpyspLLNy1wb2vfCsV2 TYPE=developer ``` `--home` points straight at a folder on disk. `--instance` / `-i` instead resolves through the instance registry (`arc service list`); `did list` itself never needs a running daemon, but the name still has to be one you actually created: ```bash $ arc did list -i doc519-nonexistent ERROR: no instance named "doc519-nonexistent". `arc service list` shows 5 ``` Exit `1`. (The number after `shows` is how many instances this machine had at capture time — it says nothing about the name you typed.) A real instance works whether its daemon is running or stopped — `arc service start` already generated it a `developer` identity, which is why the first `did list` against a fresh instance is not empty the way a bare `--home` folder is: ```bash $ arc service start -i doc519didlist --home /tmp/arc-doc519-instance-home --port 0 ... Status: up $ arc did list -i doc519didlist developer DID=z1jhrDL9b5Et2jgSZJwPkL324R4aVaXBHbf TYPE=developer $ arc service stop -i doc519didlist Service stopped: doc519didlist $ arc did list -i doc519didlist developer DID=z1jhrDL9b5Et2jgSZJwPkL324R4aVaXBHbf TYPE=developer ``` (splash banner lines omitted from the `service start`/`service stop` output above.) `--json` returns the same rows as structured data: ```bash $ arc did list -i doc519didlist --json { "identities": [ { "name": "developer", "did": "z1jhrDL9b5Et2jgSZJwPkL324R4aVaXBHbf", "entityType": "developer" } ], "total": 1, "hintSelector": "-i doc519didlist" } ``` ## Credentials ### arc did issue Issue a verifiable credential. **Usage** ```bash arc did issue [options] ``` - **`--skip-check`**: skip the conformance check - **`--counter-sign`**: counter-sign an existing VC with a trusted issuer key - **`--issuer-key `**: path to the issuer key file, used with `--counter-sign` - **`--expiration `**: expiration date, ISO format - **`--all`**: issue VCs for all entities (providers + blocklets) - **`--trust`**: auto-register the issuer as trusted after counter-signing ### arc did verify Verify a credential. ```bash arc did verify ``` ## Trusted issuers `arc did issuer` manages the list of issuers your setup trusts. ```bash arc did issuer [options] ``` ### arc did issuer list List all trusted issuers. **Example** ```bash $ arc did issuer list No trusted issuers ``` ### arc did issuer add Add a trusted issuer. **Usage** ```bash arc did issuer add [options] ``` - **`--name `** (required): issuer identifier, used as filename prefix - **`--from-key `**: path to a key file containing DID and public key - **`--from-file `**: path or HTTPS URL to a `.did.json` file - **`--from-vc `**: path to a VC file, extracts the counter-sign proof signer - **`--proof-index `**: select a specific proof by index, for `--from-vc` with multiple proofs - **`--did `**: DID address, base58 `z...` format - **`--pk `**: public key, hex format ### arc did issuer remove Remove a trusted issuer. ```bash arc did issuer remove ``` ### arc did issuer inspect Show detailed information about a trusted issuer. ```bash arc did issuer inspect ``` ### arc did issuer reset Reset the trust store: remove manually-added issuers. This build has no shipped seed set to restore — on a clean home the command is a no-op. **Usage** ```bash arc did issuer reset [options] ``` - **`--yes`**: skip the confirmation prompt (required when stdin is not a TTY) **Example** (clean home) ```bash $ arc did issuer reset --yes RESET no-op $ arc did issuer list No trusted issuers ``` `--help` still says "restore shipped seeds"; that one-liner does not match this build. `--json` reports `{"removed":[],"restored":[]}`. After you add an issuer, the same `--yes` command prints `REMOVED ` and `arc did issuer list` again reports `No trusted issuers`. --- ## arc drain URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-drain/ `arc drain` is a real CLI process, not a chat turn — killing whatever session started it does not stop draining unless this process itself is killed. It subscribes to `/dev/code-agents` (or the path you pass with `--subscribe-path`), and on each wake it claims ready work from the work ledger and execs `/dev/code-agents/.actions/run` with the claimed work. An empty ready set exits `0`; `arc drain` never creates ledger rows itself, it only consumes them. **Usage** ```bash arc drain --cwd [options] ``` - **`--cwd `** (required, no default): working directory passed to `/dev/code-agents/.actions/run`. Must **not** be the daemon's own project checkout - **`--work-root `**: work collection root, i.e. which AFS path holds the work records (default `/work`) - **`--subscribe-path `**: AFS path prefix to subscribe for wakes, e.g. `/dev/code-agents` or `/settled` (default `/dev/code-agents`) - **`--engine `**: restrict dispatch to this engine id (default: first idle dispatch target) - **`--peer `**: restrict dispatch to this peer id (default: first idle online peer) Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). `--standalone` is also global (ad-hoc mode: load AFS from the current directory's local config instead of a running daemon). Drain is normally left against the default instance unless you pass `--instance`. `arc drain` expects the target instance's daemon to already be up (e.g. via `arc service start`). Letting `drain` auto-start it instead boots a leaner AFS that skips the default `/work` mount, so it fails with `No module found for path: /work in namespace 'default'` before ever reaching the ledger. **Example** (empty ready set, daemon already running) ```bash $ arc drain --cwd /path/to/a/work/tree ready set empty ``` Press Ctrl-C (SIGINT) or send SIGTERM to stop draining; either aborts the current wait cleanly. **Example** (missing the required flag) ```bash $ arc drain ERROR: --cwd is required (no default — must not be the daemon's own project checkout) ``` --- ## arc dsl URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-dsl/ `arc dsl` works with AUP DSL, the declarative language `.aup` files (like a page's `layout.aup`) are written in. Every subcommand except `lsp` takes a path (an `.aup` file or a blocklet directory) and defaults to the current directory. Captured against `arc` `2.0.0-beta.50` (commit `a99fb2c37`, main, 2026-09-11). Run `arc --version` before you copy dumps; the commit is what pins the command surface. ```bash arc dsl [path] [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). ### arc dsl lint Check DSL formatting and semantic validity. This is one of the four checks this repo's own merge gate runs. **Usage** ```bash arc dsl lint [path] [options] ``` - **`--fix`**: apply all safe lint fixes before linting - **`--fix-format`**: rewrite DSL sources with canonical formatting - **`--fix-ids`**: remove unreferenced explicit ids from page DSL sources - **`--fix-locales`**: prune locale JSON keys not referenced by DSL sources ### arc dsl validate Validate an `.aup` file or blocklet directory. The second of the four merge-gate checks. ```bash arc dsl validate [path] ``` **Example** ```bash $ arc dsl validate Passed DSL validation path: /path/to/your/blocklet files: 368 Next: arc blocklet build /path/to/your/blocklet ``` On success it prints a `Next:` hint pointing at the next command to run (`arc blocklet build`); on failure it reports each problem as `ERROR path:line:col: message`. This is the only `dsl` subcommand that prints a `Next:` hint — `lint`, `format`, `generate`, `decompile`, `doctor`, and `migrate-i18n` do not. ### arc dsl schema Print the AUP DSL language schema and primitive metadata. ```bash arc dsl schema [path] ``` **Example** ```bash $ arc dsl schema Passed DSL schema path: /path/to/your/blocklet root: /path/to/your/blocklet primitives: 63 aliases: 12 snippets: 4 files: 0 ``` These counts are per-project: a blocklet that defines its own primitives (via `.scaffold/*.dsl`) reports a higher `primitives` number than a plain blocklet, and the built-in tally itself changes as the DSL language gains primitives across releases — run the command to see the current numbers rather than treating any fixed number here as canonical. ### arc dsl format Format page `.aup` files. **Usage** ```bash arc dsl format [path] [options] ``` - **`--check`**: fail if formatting would change files - **`--write`**: rewrite files in place ### arc dsl generate Generate `app.json` and page JSON artifacts from `app.aup`. **Usage** ```bash arc dsl generate [path] [options] ``` - **`--check`**: fail if generated artifacts would change - **`--write`**: rewrite generated artifacts in place On a fresh `minimal-app` scaffold with zero edits, `--check` currently exits 5 (`generated_changed` on `.aup/app.json`, `.aup/pages/agent.json`, `.aup/pages/home.json`, `.aup/wrapper.json`). See the check chain under [arc blocklet create](../command-reference-blocklet/#arc-blocklet-create). ### arc dsl decompile Decompile generated AUP JSON artifacts back into AUP DSL sources, the reverse of `generate`. **Usage** ```bash arc dsl decompile [path] [options] ``` - **`--check`**: fail if decompiled DSL would change files - **`--write`**: rewrite decompiled DSL files in place - **`--partial`**: write sources that can be decompiled, downgrade missing page artifacts to warnings instead of failing ### arc dsl doctor Run decompile, format, regenerate-check, and validate together, a one-command health check for DSL artifacts. **Usage** ```bash arc dsl doctor [path] [options] ``` - **`--check`**: fail if doctor would change files - **`--write`**: rewrite decompiled DSL files in place before verifying On that same zero-edit `minimal-app` scaffold, `arc dsl doctor` currently exits 5 (`decompile step: failed (0 files, 0 changed)`). Same transcript as the check chain under [arc blocklet create](../command-reference-blocklet/#arc-blocklet-create). ### arc dsl migrate-i18n Move exact `$t(page.key)` strings into page-local inline i18n blocks. **Usage** ```bash arc dsl migrate-i18n [path] [options] ``` - **`--check`**: fail if migration would change files - **`--write`**: rewrite page DSL and locale JSON files in place ### arc dsl language Inspect DSL diagnostics, completions, and hover metadata, the machinery behind editor integrations. **Usage** ```bash arc dsl language [path] [options] ``` - **`--line `**: one-based line for completion/hover lookup - **`--column `**: one-based column for completion/hover lookup ### arc dsl lsp Start a JSON-RPC language server for AUP DSL editor integrations. ```bash arc dsl lsp ``` --- ## arc mcp URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-mcp/ `arc mcp` bridges stdio to the running AFS daemon's MCP endpoint. It auto-starts the daemon if it isn't already running. **Usage** ```bash arc mcp [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). - **`--port `**: daemon port, 1-65535 (omit, or pass `0`, to use the instance registry / seed `default` on `4900`) **Example** (auto-starts the daemon; blocks on stdio afterward) ```bash $ arc mcp Starting AFS service... ``` A port already held by another instance is a reject path, exit `1`: ```bash $ arc mcp --port 4900 Starting AFS service... ERROR: Failed to start service: Port 4900 is already in use ``` **Claude Desktop config** ```json { "mcpServers": { "AFS": { "command": "arc", "args": ["mcp"] } } } ``` `arc mcp` is a bridge, not a standalone MCP server. If you want a standalone one, use `arc serve --transport mcp-stdio` (loads AFS directly) or `arc serve --transport mcp-http`. --- ## arc network URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-network/ `arc network` answers one question: can this machine reach the outside world the way `arc` needs to? It has a single subcommand, `doctor`, which runs four checks — proxy discovery, DNS, an HTTPS request, and a WebSocket handshake — and reports each on its own line. They are reported separately on purpose: "DNS resolves but the proxy refuses CONNECT" and "nothing resolves at all" are different faults with different fixes, and a single pass/fail would hide which one you have. Captured against `arc` `2.0.0-beta.48` (commit `5a5316bde`, 2026-09-10). The version number alone does not pin this — `2.0.0-beta.48` has named more than one binary this cycle — so run `arc --version` and compare its third field, the commit, against the one above before trusting anything below byte-for-byte; checks and flags can move between releases regardless. **Usage** ```bash arc network doctor [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). `doctor` does not talk to a daemon, so it works whether or not one is running. - **`--target `**: HTTPS URL to probe (default `https://main.abtnetwork.io/`) - **`--ws-target `**: WSS URL to probe (default `wss://main.abtnetwork.io/api/websocket?vsn=2.0.0`) `arc network` on its own is not a command: it prints `Please specify a subcommand` along with the subcommand list, and exits `5`. **Example** (everything reachable, no proxy) ```bash $ arc network doctor Outbound network doctor Proxy: (none) Checks: ✓ proxy-discovery no proxy environment variables ✓ direct-dns main.abtnetwork.io → 198.18.0.38 ✓ https-through-proxy HTTP 200 direct ✓ wss-through-proxy WSS handshake direct OK ``` All four passing exits `0`. The two network checks keep `through-proxy` in their names even when no proxy is involved; the detail column is what tells you which route was actually taken — `direct` here. **The address on the `direct-dns` line is whatever your own resolver returns**, so expect a different one, and on a network with a captive or filtering resolver expect an address the name does not really have. This is worth more than a footnote, because the layer a failure gets attributed to follows the resolver: a name that does not exist is reported as a DNS failure where the resolver says so, and as a connection or TLS failure where the resolver answers anyway. When a `doctor` result surprises you, confirm the name independently before believing which check went red. **Example** (a proxy is configured but not answering) ```bash $ HTTPS_PROXY=http://127.0.0.1:9 HTTP_PROXY=http://127.0.0.1:9 arc network doctor ERROR: Outbound network doctor Proxy: HTTP_PROXY http://127.0.0.1:9/ HTTPS_PROXY http://127.0.0.1:9/ Checks: ✓ proxy-discovery proxy environment variables present (credentials redacted) ✓ direct-dns main.abtnetwork.io → 198.18.0.38 ✗ https-through-proxy PROXY_CONNECT_FAILED connect ECONNREFUSED 127.0.0.1:9 ✗ wss-through-proxy PROXY_CONNECT_FAILED connect ECONNREFUSED 127.0.0.1:9 FAILED ``` Any failing check exits `5`. The `ERROR: ` prefix on the first line is the CLI's one sole marker for "this run failed" (arc#6301) — every failure the CLI reports, from any command, starts a message this same way, so a caller can find the front of an error without knowing which command produced it. Notice what stayed green: proxy discovery passed because it only reports which variables are set, not whether the proxy works, and DNS passed because resolution never went through the proxy at all. The two that failed name the reason — `PROXY_CONNECT_FAILED` — instead of a generic timeout, which is what tells you to look at the proxy rather than at DNS or at the target host. Proxy URLs are printed with any credentials redacted. **Machine-readable output** `--json` prints the same run as structured data. Below is the failing run above, because failure is where the interesting fields appear: each failed check gains a `code`, and `required` / `affectsOverallHealth` say which results the verdict is computed from. `direct-dns` flips to `required: false` here — once a proxy is in play, resolving directly is no longer something the verdict depends on. ```bash $ HTTPS_PROXY=http://127.0.0.1:9 HTTP_PROXY=http://127.0.0.1:9 arc network doctor --json ERROR: { "proxy": { "httpProxy": "http://127.0.0.1:9/", "httpsProxy": "http://127.0.0.1:9/" }, "checks": [ { "name": "proxy-discovery", "ok": true, "status": "pass", "required": true, "affectsOverallHealth": true, "detail": "proxy environment variables present (credentials redacted)" }, { "name": "direct-dns", "ok": true, "status": "pass", "required": false, "affectsOverallHealth": false, "detail": "main.abtnetwork.io → 198.18.0.38" }, { "name": "https-through-proxy", "ok": false, "status": "fail", "required": true, "affectsOverallHealth": true, "code": "PROXY_CONNECT_FAILED", "detail": "connect ECONNREFUSED 127.0.0.1:9" }, { "name": "wss-through-proxy", "ok": false, "status": "fail", "required": true, "affectsOverallHealth": true, "code": "PROXY_CONNECT_FAILED", "detail": "connect ECONNREFUSED 127.0.0.1:9" } ], "ok": false } ``` The leading `ERROR: ` above is real and not a copy-paste mistake: on a failing run the same one-sink prefix from the human example lands in front of the JSON too, on the same line as the opening `{`, because a failed command's whole message — human text or JSON, this CLI does not distinguish at that point — gets the marker prepended once. Strip that one token before parsing on a non-zero exit, or route on the exit code instead of trying to parse stderr as JSON at all. A clean run is the same shape with the `code` fields absent, every `status` set to `pass`, `proxy` an empty object, and the top-level `ok` true — and no `ERROR: ` prefix, because it only appears on failure. One more thing worth knowing before you pipe this: on a failing run **stdout is 0 bytes** — the whole message, prefix and all, goes to stderr — so `arc network doctor --json | jq` sees nothing at all rather than an error object; check the exit code first, or you will end up debugging your `jq` filter instead of the actual failure. The two targets move independently. `--target` retargets the HTTPS probe and the DNS check with it — probing `https://arc.arcblock.io/` puts `arc.arcblock.io → …` on the `direct-dns` line instead of the default host — while `--ws-target` moves only the WebSocket probe, leaving DNS on whatever `--target` names. Aiming `--ws-target` at a closed port therefore fails exactly one check: ```bash $ arc network doctor --ws-target wss://127.0.0.1:9/ ERROR: Outbound network doctor Proxy: (none) Checks: ✓ proxy-discovery no proxy environment variables ✓ direct-dns main.abtnetwork.io → 198.18.0.38 ✓ https-through-proxy HTTP 200 direct ✗ wss-through-proxy UPSTREAM_REJECTED FAILED ``` A literal address and a closed port were chosen here so the probe fails the same way on every machine — no name to resolve means no resolver to disagree. What names the failed layer is the `code`, `UPSTREAM_REJECTED`, distinct from `PROXY_CONNECT_FAILED` / `DIRECT_DNS_FAILED` / `TLS_FAILED`; the free-text detail after it is not guaranteed and came back empty in this capture — an immediately-refused loopback connection did not leave the underlying socket layer anything to say. Do not match on the detail text; match on the `code`, in `--json` if you need it structured. Use these two flags when the defaults are reachable but the host you actually care about is not. --- ## arc provider URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-provider/ `arc provider` handles operations on provider packages themselves (the npm packages that implement AFS providers), as opposed to `arc afs`, which operates on what a provider exposes once mounted. ```bash arc provider [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). ### arc provider publish-resources Publish a provider package's `aup/` tree to CF Pages, under `/_providers/@/`. This is how a provider's companion resources (like UI snippets referenced from AUP) become fetchable by URL. **Usage** ```bash arc provider publish-resources [options] ``` - **`package`** (required): npm package name, e.g. `@aigne/afs-ocap`, or a path to the package directory - **`--cloud `**: deploy target: `fs` writes a local Pages dir, `cf` pushes to Cloudflare Pages, `none` stages into `~/.afs/blocklets-staging` without pushing, for batch deploys where only the last command should push (default `fs`) - **`--pages-root `**: local Pages store root, only for `--cloud fs` (default `~/.arc/pages`) - **`--cf-account-id `**: Cloudflare account ID, used for `--cloud cf` read operations - **`--cf-api-token `**: Cloudflare API token, used for `--cloud cf` read operations - **`--deployment `**: Cloudflare deployment id (staging/prod/...), resolves `pagesProject` from `runtimes/cloudflare/instances.json`; mutually exclusive with `--project` - **`--project `**: Pages project name, an escape hatch for projects not in `instances.json`; mutually exclusive with `--deployment`; defaults to `afsd-blocklets` when neither is set The `--deployment`/`--project` exclusion is declared and enforced, not just documented: ```bash $ arc provider publish-resources @aigne/afs-ocap --deployment foo --project bar ERROR: Arguments deployment and project are mutually exclusive ``` A real package publishes to `--cloud fs` without either flag (the cumulative-staging count keeps growing with every publish to that store, so yours will differ): ```bash $ arc provider publish-resources ./providers/runtime/ocap --cloud fs --pages-root /tmp/pages Published 23 file(s) to /_providers/ocap@2.0.0-beta.48/ package: ./providers/runtime/ocap provider: ocap@2.0.0-beta.48 bytes: 170952 target: local Pages store (cumulative staging: 1983 file(s)) deploy: deploy-1789005081569-e83ray ``` --- ## arc serve URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-serve/ `arc serve` starts an AFS server, over HTTP or MCP, so something other than the CLI itself (a browser, an agent, an MCP client) can talk to your AFS instance over the network. **Usage** ```bash arc serve [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). - **`--host `**: host to bind (default `localhost`) - **`--port `**: port to listen on (default `3000`) - **`--path `**: base path for the API (default `/afs`) - **`--readonly`**: read-only mode - **`--cors`**: enable CORS; pass no value for off, `*` for any origin, or a comma-separated allowlist - **`--transport `**: transport mode (default `http`). `mcp-http` is local-dev-only by design, it has no Bearer token support - **`--token `**: require a Bearer token on every request; overrides `serve.token` from config - **`--insecure-no-auth`**: explicitly serve without an auth token when binding to a non-loopback host. Dangerous, anyone who can reach the bound address gets full AFS access This is different from `arc service`, which manages named long-running background instances. `arc serve` is a foreground process for a single session. See [arc service](../command-reference-service/). **Example** ```bash $ arc serve --port 4000 --cors '*' AFS HTTP Server starting... Mounted providers: ... Listening on: http://localhost:4000/afs Press Ctrl+C to stop ``` --- ## arc service URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-service/ `arc service` manages named AFS background instances. `arc afs`, MCP bridging, and blocklet serving all depend on a running instance. Captured against `arc` `2.0.0-beta.48`, commit `5a5316bde` (main, 2026-09-10) — not the published binary of the same version string; two different builds have carried `2.0.0-beta.48` at once, so this page is pinned to the commit, not the semver. `arc service` is **nine real subcommands** (`arc service [options]`), each with its own `--help` and `Examples:` block — not one command with a positional `action` choice list. `--json` reject path remeasured after ArcBlock/arc#5205 (error object on stdout — corrected again below, see [`--json` contract](#json-contract)); `delete` became the primary action name after ArcBlock/arc#5279 (`rm`/`remove` are now aliases); the subcommand split and the `ERROR: ` prefix on every failure line are both ArcBlock/arc#6301. Positional instance names were removed in ArcBlock/arc#5713: the only way to pick an instance is `--instance` / `-i`. Run `arc --version` before you copy dumps; verbs and flags can still move. `--help` text below is English (`LC_ALL=C`) — since ArcBlock/arc#5244, help/error text is always English regardless of your system locale. Instance names, home paths and ports below are shortened to a readable `docs514a` / `/tmp/arc-svc-docs-514/...` form; the message text, field names, exit codes and JSON shapes are copied verbatim from a real run. ```bash arc service [options] ``` `verb` is one of `list` (`ls`, `ps`), `start`, `stop`, `restart`, `status`, `delete` (`rm`, `remove`), `gc` (`prune`), `url`, `logs` (`log`). Pick the instance with `--instance ` / `-i`. Omit `--instance` to operate on the seed instance `default` (home `~`, port `4900`). Any other name gets a kernel-assigned port unless you pass `--port`. Do not `stop` or `delete` a seed instance you did not start. The dumps on this page used a throwaway registry and never touched the machine's `default` on `:4900`. ## Isolation Named instances plus `--home` are the isolation mechanism. `ARC_HOME` is **retired**: the CLI warns and ignores the value. ```bash export ARC_INSTANCES_DIR=/tmp/arc-svc-docs-514/instances arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b ``` `ARC_SERVICE_PORT` still exists, but it only affects the unnamed seed instance. Prefer a name, or pass `--port`. Splash banner lines on stderr are omitted in the dumps below. ## Subcommands Each subcommand carries its own `--help` and its own `Examples:` (see the [`--help`](#help) section at the bottom of this page). `arc service ` and `arc service` with no verb both print the group listing below, not a per-verb one. | Subcommand | Aliases | What it does | | --- | --- | --- | | `list` | `ls`, `ps` | List every local instance with its status, port and home | | `start` | | Start an instance, creating it on first use | | `stop` | | Stop a running instance, keeping its record and data | | `restart` | | Restart an instance from its recorded config — does not reconfigure; `stop` then `start` for that | | `status` | | Report whether an instance is running, and on which port | | `delete` | `rm`, `remove` | Delete an instance: its record and its data | | `gc` | `prune` | Drop registry records whose process is gone | | `url` | | Print an instance's base URL (and its blocklets') | | `logs` | `log` | Print an instance's daemon log | ## Flags Every subcommand accepts the shared globals — `--json`, `--view`, `--home`, `--instance` / `-i`, `--print` — plus its own extra flags: | Flag | Subcommand(s) | Meaning | | --- | --- | --- | | `-i`, `--instance` | all | Named local ARC instance this command operates against. Omit for `default`. This is the only way to pick an instance | | `--home` | all | Instance root. Used by `start` (create) and `arc did init`. On `restart` it is cross-checked against the recorded home rather than accepted as new config — matching it is a no-op, naming a different path is rejected (see [Failures](#failures)) | | `--print` | all | Print one result field (for example `url`, `port`) as plain text — not a view; overrides `--json`/`--view`. See [`--print`](#print) below | | `--port` | `start` | Listen port (0–65535). `0` = auto-assign. Omit: `default` uses `4900`, named instances use the recorded port or auto-assign | | `--host` | `start` | Bind address (`localhost`, `0.0.0.0`, `::`, or a unicast IP). Default `localhost` | | `--advertise` | `start` | Advertise over mDNS when bind is non-loopback (default `true`; `--no-advertise` disables) | | `--blocklet` | `start` | Blocklet-parent or single-blocklet dir to serve (repeatable). Recorded on the instance | | `--space-root` | `start` | Folder-as-DID-Space from `arc space init`. Omit to derive from `--home` | | `--force` | `delete` | Stop a running instance before deleting it. Default `false` | | `--dry-run` | `delete` | Print what would be removed without deleting it. Default `false` | | `--yes` | `delete` | Skip the TTY confirmation prompt. Default `false` | | `--follow` | `logs` | Stream new lines as they are written. Default `false` | `--yaml` was removed, never implemented — see [Overview](../overview/). `restart` has none of `start`'s config flags in its own `--help` — passing one is refused with a dedicated message, not yargs' generic "unknown argument" (that generic path is what genuinely-removed flags like `--blocklet-dir` hit; see [Removed and retired](#removed-and-retired)): ```bash $ arc service restart --instance docs514a --port 4910 ERROR: restart does not reconfigure. use `stop` then `start` to change --port ``` `--home` is the one exception: it is a global flag, so `restart --home ` succeeds silently (a no-op), and only a **different** path is rejected — with a different message and exit code than the config-flag guard above: ```bash $ arc service restart --instance docs514a --home /tmp/somewhere-else ERROR: --instance "docs514a" and --home "/tmp/somewhere-else" name different instances (instance "docs514a" is registered at "/tmp/arc-svc-docs-514/home-a") ``` (exit `5`, versus exit `1` for `--port`/`--host`/`--advertise`/`--space-root`/`--blocklet`.) ## States | Status | Meaning | | --- | --- | | `starting` | Record claimed, process not yet `up` | | `up` | Process is listening | | `stopped` | Process exited through `stop`. `start` / `restart` reuse the record | | `dead` | Process gone without a clean stop. `gc` removes only this state | `list` shows the **recorded** port for every non-`up` row, suffixed `*` to mark it last-known rather than live (`stopped`/`dead` both get the suffix); `-` appears only when there is no recorded port at all (an instance that never reached `up`): ``` NAME ID PORT STATUS HOME SOURCES docs514a b719db414c5cc62 61497* stopped /tmp/arc-svc-docs-514/home-a 1 ``` `status` exits `0` for `up`, `3` for `starting` / `stopped`, and `4` for `dead`. For anything but `up` it still reports the pid / port / URL from the last run, and marks them as such (`lastKnown` in `--json`, a `Note:` line in the human view). ## Start, list, status, url Empty registry: ```bash $ export ARC_INSTANCES_DIR=/tmp/arc-svc-docs-514/instances $ arc service list NAME ID PORT STATUS HOME SOURCES (no instances) ``` Start a named instance. Port `61497` was kernel-assigned, not `4900`: ```bash $ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a Instance: docs514a ID: b719db414c5cc624 Status: up PID: 95665 Port: 61497 URL: http://127.0.0.1:61497 Home: /tmp/arc-svc-docs-514/home-a Space: /tmp/arc-svc-docs-514/home-a/.afs/spaces Sources: - Version: 2.0.0-beta.48 Commit: 5a5316bde Checkout: /tmp/arc-svc-docs-514/project Host: localhost Started: 2026-09-10T01:52:25.130Z (up 2s) ``` Progress, log path, build id, and endpoints went to stderr. The instance record went to stdout — stderr on this capture (omitting the banner): ``` Starting AFS service... AFS Service started Log: /tmp/arc-svc-docs-514/home-a/.afs/daemon.log Build: 2.0.0-beta.48+5a5316bde (debug) Exec: /path/to/arc/runtimes/node/dist/cli.mjs Endpoints: http://127.0.0.1:61497/ AUP Web Client http://127.0.0.1:61497/explorer Explorer UI http://127.0.0.1:61497/ws WebSocket (Explorer) http://127.0.0.1:61497/afs/* REST API http://127.0.0.1:61497/mcp MCP Streamable HTTP ``` `Build` / `Exec` come from `/.afs/daemon.build.json`, which the daemon writes on boot; on an older daemon that has no sidecar the two lines are omitted rather than guessed. `Version` / `Commit` / `Checkout` describe the binary that is actually serving the instance — see [Identity fields](#identity-fields) below. Record a blocklet source with `--blocklet` (repeatable). Same flag accepts a parent directory or a single blocklet directory: ```bash $ arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b \ --blocklet /path/to/arc/blocklets/afs-preview-fixture --host 127.0.0.1 --no-advertise Instance: docs514b ID: b719db414c5cc625 Status: up PID: 95666 Port: 61498 URL: http://127.0.0.1:61498 Home: /tmp/arc-svc-docs-514/home-b Space: /tmp/arc-svc-docs-514/home-b/.afs/spaces Sources: /path/to/arc/blocklets/afs-preview-fixture Version: 2.0.0-beta.48 Commit: 5a5316bde Checkout: /tmp/arc-svc-docs-514/project Host: 127.0.0.1 Started: 2026-09-10T01:49:56.435Z (up 7s) ``` stderr for that run added an `Extra blocklet dirs:` line before the banner-omitted `AFS Service started`, and a `Blocklet:` block after `Endpoints:`: ``` Starting AFS service... Extra blocklet dirs: /path/to/arc/blocklets/afs-preview-fixture AFS Service started Log: /tmp/arc-svc-docs-514/home-b/.afs/daemon.log Build: 2.0.0-beta.48+5a5316bde (debug) Exec: /path/to/arc/runtimes/node/dist/cli.mjs Endpoints: http://127.0.0.1:61498/ AUP Web Client http://127.0.0.1:61498/explorer Explorer UI http://127.0.0.1:61498/ws WebSocket (Explorer) http://127.0.0.1:61498/afs/* REST API http://127.0.0.1:61498/mcp MCP Streamable HTTP Blocklet: afs-preview-fixture http://afs-preview-fixture.localhost:61498/ http://localhost:61498/?blocklet=afs-preview-fixture (Safari / universal) ``` ```bash $ arc service list NAME ID PORT STATUS HOME SOURCES docs514a b719db414c5cc624 61497 up /tmp/arc-svc-docs-514/home-a 0 docs514b b719db414c5cc625 61498 up /tmp/arc-svc-docs-514/home-b 1 ``` `status` reports everything `start` reported, for an instance you did not just start — same stdout/stderr split: ```bash $ arc service status --instance docs514b Instance: docs514b ID: b719db414c5cc625 Status: up PID: 95666 Port: 61498 URL: http://127.0.0.1:61498 Home: /tmp/arc-svc-docs-514/home-b Space: /tmp/arc-svc-docs-514/home-b/.afs/spaces Sources: /path/to/arc/blocklets/afs-preview-fixture Version: 2.0.0-beta.48 Commit: 5a5316bde Checkout: /tmp/arc-svc-docs-514/project Host: 127.0.0.1 Started: 2026-09-10T01:49:56.435Z (up 3m) ``` Log path, build id, endpoints, blocklet URLs and (on a non-loopback bind) the LAN diagnostic go to stderr; the record goes to stdout. `start` and `status` print the same URL for the same instance — both use the registry's `http://127.0.0.1:` form. `--json` suppresses the stderr blocks and carries all of it as data instead. On a machine whose project root exposes many blocklets, `status` expands only the routes you named with `--blocklet` and counts the rest — this is a real capture against a full dev checkout, not a contrived number: ``` Blocklets: 51 route(s) served — 50 not expanded; `arc service url` or --json lists them all ``` `--json` always carries every route in `urls.blocklets`. ```bash $ arc service url --instance docs514b http://127.0.0.1:61498/ ``` stderr (banner omitted), same printer as `start`: ``` Blocklet: afs-preview-fixture http://afs-preview-fixture.localhost:61498/ http://localhost:61498/?blocklet=afs-preview-fixture (Safari / universal) ``` ```bash $ arc service url --instance docs514b --print url http://127.0.0.1:61498 ``` `--print url` writes only the instance URL to stdout (no trailing slash in this capture), exit `0`. `$(arc service url --instance NAME)` stays that one line. Agents that need a blocklet address use `--json` and the **Host** URL (`http://afs-preview-fixture.localhost:…`). `?blocklet=` is the Safari fallback; it does not mount `/blocklets/` for RPC. ### Identity fields `Version` / `Commit` / `Branch` / `Sha` / `Checkout` describe **the binary serving this instance**, not the `arc` you typed. The daemon computes them at boot and writes them into its registry row, so a `status` from any shell reports the same values as `curl http://127.0.0.1:/.well-known/arc/instance`. For an `up` instance, `status` asks the daemon directly and reports the answer under `live`: ```json "live": { "ok": true, "url": "http://127.0.0.1:61498/.well-known/arc/instance", "record": { "version": "2.0.0-beta.48", "commit": "5a5316bde", "pid": 95666, "port": 61498, "blocklets": 1 } } ``` If the registry row and the daemon disagree — which is what `arc upgrade` does, swapping the binary under a running process — both values are reported and the differing fields are listed under `drift`: ```json "drift": [{ "field": "version", "registry": "2.0.0-beta.48", "live": "2.0.0-beta.49" }] ``` The probe is best effort. If the process is alive but nothing answers on loopback in time — captured here from a `SIGSTOP`ped daemon, which is why the exact wording is a timeout rather than a refused connection — `status` falls back to the registry view and says so; the exit code is unchanged: ``` Live: unreachable (The operation was aborted due to timeout) — registry values only ``` (A daemon that is fully gone rather than merely unresponsive reports `dead` instead — see [States](#states) — and is not probed at all.) ## Restart, logs, stop, delete, gc `restart` reuses the record. It does not take a new `--port`: ```bash $ arc service restart --instance docs514b Instance: docs514b ID: b719db414c5cc625 Status: up PID: 95700 Port: 61498 URL: http://127.0.0.1:61498 Home: /tmp/arc-svc-docs-514/home-b Space: /tmp/arc-svc-docs-514/home-b/.afs/spaces Sources: /path/to/arc/blocklets/afs-preview-fixture Version: 2.0.0-beta.48 Commit: 5a5316bde Checkout: /tmp/arc-svc-docs-514/project Host: 127.0.0.1 Started: 2026-09-10T01:58:00.472Z (up 3s) ``` stderr says `AFS Service restarted` (not `started`), otherwise the same shape as `start`'s stderr above. ```bash $ arc service logs --instance docs514b {"ts":"2026-09-10T01:58:01.683Z","level":"info","service":"arc-node","ns":"node:boot","message":"boot vault-ready +652ms"} {"ts":"2026-09-10T01:58:01.686Z","level":"info","service":"arc-node","ns":"node:boot","message":"boot did-space-ready +656ms"} {"ts":"2026-09-10T01:58:02.235Z","level":"info","service":"arc-node","ns":"node:boot","message":"[code-agents] recover ok: claimed=0 marked=0 orphaned=0 deferred=0 locksScanned=0 locksReclaimed=0"} ``` Later boot lines omitted. `--follow` reprints existing lines then streams. ```bash $ arc service stop --instance docs514b Service stopped: docs514b ``` A `stopped` instance still reports its last pid / port / URL, and says in words that those are historical (exit `3`): ```bash $ arc service status --instance docs514b Instance: docs514b ID: b719db414c5cc625 Status: stopped PID: 95700 Port: 61498 URL: http://127.0.0.1:61498 Home: /tmp/arc-svc-docs-514/home-b Space: /tmp/arc-svc-docs-514/home-b/.afs/spaces Sources: /path/to/arc/blocklets/afs-preview-fixture Version: 2.0.0-beta.48 Commit: 5a5316bde Checkout: /tmp/arc-svc-docs-514/project Host: 127.0.0.1 Started: 2026-09-10T01:58:00.472Z Note: PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process. ``` In `--json` the same fact is `"lastKnown": true`, and there is no `live` key — a stopped instance is not probed. `list` prints `*` for PORT (see [States](#states)). `start` on the same name reuses the record. Each code block on this page is its own capture; instance names repeat across sections (`docs514a`, `docs514b`) without implying one continuous session — the four `delete` examples below use fresh throwaway names for exactly that reason, so none of them is a delete on a name a previous example already removed. `delete` now has two output shapes for success, split by view the same way `arc afs delete` is (ArcBlock/arc#6055): the **default** (machine, non-TTY) view is a bare `OK ` — write's shape — and `--view human` is a sentence naming what was removed. Both instances below were `stopped` before the delete: ```bash $ arc service delete --instance docs514x OK docs514x $ arc service delete --instance docs514y --view human Removed instance "docs514y" ``` `delete` of a **running** instance fails without `--force` — this is also where the ArcBlock/arc#6301 prefix fix actually shows up: every failure line on this page now starts `ERROR: ` where the old capture had no prefix at all: ```bash $ arc service delete --instance docs514z ERROR: instance "docs514z" is running. stop it first, or use --force ``` `--force` stops first, then deletes — the accept-path counterpart to the reject above, same instance, same verb: ```bash $ arc service delete --instance docs514z --force --yes OK docs514z ``` `--dry-run` previews without touching anything, and works on either a stopped or a running instance: ```bash $ arc service delete --instance docs514w --dry-run Would delete instance docs514w at /tmp/arc-svc-docs-514/home-w (dry-run) $ arc service delete --instance docs514w --dry-run --json { "name": "docs514w", "removed": false, "home": "/tmp/arc-svc-docs-514/home-w", "dryRun": true, "homeRemoved": true } ``` `homeRemoved` here means "the home directory *would be* removed by a real run", not that anything was removed — `removed: false` / `dryRun: true` on the same object say that already; read the three fields together, not `homeRemoved` alone. `--yes` skips the interactive TTY confirmation prompt. In practice this rarely matters outside a real terminal: confirmation is TTY-only by design (`interactive` requires stdin *and* stdout to be a real TTY), so an agent, a pipe, or a test — anything already used to produce this page's dumps — proceeds without ever seeing the prompt, `--yes` or not. Pass it anyway for a script that might one day run from a terminal. `gc` only collects `dead` (process gone without `stop`). `stopped` is kept: ```bash $ arc service gc Collected 1 dead instance docs514dead kept 1 $ arc service gc No dead instances to collect ``` After that `list` still showed the `stopped` and `up` rows; `docs514dead` was gone. With nothing `dead` left, `gc` says so in one line and still exits `0`. A separate, freshly-emptied registry (zero instances registered at all, not the one above) makes the point that `kept` is a real count down to `0`, not an empty answer — the same "renders to zero characters, not falsy" rule the [`--print`](#print) section covers next: ```bash $ arc service gc --json { "removed": [], "kept": 0 } ``` ## `--print` `--print ` reads one field out of the command's normal result and writes it to stdout as plain text, bypassing `--json`/`--view` entirely. ArcBlock/arc#6301 changed the rule for when a field counts as "no value": it used to be **falsy** (`false`, `0`, `""` were all treated as absent, printing nothing while still exiting `0` — indistinguishable from a real empty answer); it is now **renders to zero characters**. `false` and `0` are two-and-one characters respectively, so they are real answers and stay exit `0`. `Object.hasOwn` is used to find the field, not `in` (which would walk the prototype chain and answer `{}` for `--print __proto__`). Accept path — a field whose real value is the boolean `false` still prints and exits `0` (this instance was started with `--no-advertise`): ```bash $ arc service status --instance docs514b --print advertise false ``` Accept path — a field whose real value is the number `0` still prints and exits `0` (an empty registry, so `gc`'s `kept` count is genuinely zero): ```bash $ arc service gc --print kept 0 ``` (The same rule covers a `0` port; that specific case cannot be produced from a live bind — the OS never actually hands back port `0` — so the CLI's own positive-control unit test drives it directly against a synthetic `{ port: 0 }` object: `runtimes/node/test/daemon/service-print-contract.test.ts:135`.) Reject path — a field that **exists but carries no value** (`branch` / `sha` / `commit` on a checkout with no `.git`) is refused, not silently printed empty: ```bash $ arc service status --instance docs514b --print branch $ echo $? 1 ``` stderr (banner omitted): `ERROR: field "branch" in result has no value` Reject path — a field that does not exist in the result at all gets a different message, same exit code: ```bash $ arc service status --instance docs514b --print nosuchfield $ echo $? 1 ``` stderr: `ERROR: no field "nosuchfield" in result` `--print ""` used to be folded into "no `--print` given" and fall through to the full default view — so `arc service status --print "$FIELD"` with an unset `$FIELD` printed the entire human view instead of failing. It no longer does; an empty field name is looked up like any other, does not exist, and is refused the same way `nosuchfield` above is: ```bash $ arc service status --instance docs514b --print "" $ echo $? 1 ``` stderr: `ERROR: no field "" in result` ## `--json` contract **JSON is stdout only on success. On reject, stdout is always empty (0 bytes) — every failure, not just some.** This corrects an earlier version of this page that claimed the reject path put `{ "error": "…" }` on stdout; that was never true for `arc service`, and ArcBlock/arc#6301's fix note confirms the post-fix contract is explicitly "0 bytes of stdout" on every one of its nine reject scenes. The error message goes to stderr, `ERROR: `-prefixed, and the process exits non-zero. Two different kinds of reject both land on this same 0-byte-stdout shape — worth checking side by side because they come from different code paths: ```bash $ arc service status --instance no-such-xyz --json $ echo $? 1 ``` stderr: ``ERROR: no instance named "no-such-xyz". `arc service list` shows 2`` — this one never reaches the action's executor at all; instance resolution fails first. ```bash $ arc service delete --instance docs514b --json $ echo $? 1 ``` stderr: `ERROR: instance "docs514b" is running. stop it first, or use --force` — this one runs inside `delete`'s own executor, which decides to fail *after* resolving the instance successfully. Same shape either way: empty stdout, `ERROR: `-prefixed stderr, non-zero exit. `--json` does not change any of that — it only changes what a *successful* run would have printed. **On success, the JSON is a superset of the human view.** Every URL, hostname and path the terminal prints is somewhere in the payload — `logFile`, `endpoints`, `blockletUrls`, `lan`, `build` — so an agent never has to scrape stderr. ```bash $ arc service status --instance docs514b --json { "name": "docs514b", "id": "b719db414c5cc625", "status": "up", "port": 61498, "url": "http://127.0.0.1:61498", "home": "/tmp/arc-svc-docs-514/home-b", "spaceRoot": "/tmp/arc-svc-docs-514/home-b/.afs/spaces", "blocklets": [ "/path/to/arc/blocklets/afs-preview-fixture" ], "pid": 95666, "version": "2.0.0-beta.48", "commit": "5a5316bde", "branch": null, "sha": null, "checkout": "/tmp/arc-svc-docs-514/project", "startedAt": "2026-09-10T01:49:56.435Z", "urls": { "ui": "http://127.0.0.1:61498/", "blocklets": { "afs-preview-fixture": "http://127.0.0.1:61498/?blocklet=afs-preview-fixture" } }, "host": "127.0.0.1", "advertise": false, "uptime": "3s", "logFile": "/tmp/arc-svc-docs-514/home-b/.afs/daemon.log", "endpoints": [ { "url": "http://127.0.0.1:61498/", "label": "AUP Web Client" }, { "url": "http://127.0.0.1:61498/explorer", "label": "Explorer UI" }, { "url": "http://127.0.0.1:61498/ws", "label": "WebSocket (Explorer)" }, { "url": "http://127.0.0.1:61498/afs/*", "label": "REST API" }, { "url": "http://127.0.0.1:61498/mcp", "label": "MCP Streamable HTTP" } ], "blockletUrls": { "afs-preview-fixture": [ { "url": "http://afs-preview-fixture.localhost:61498/", "label": "" }, { "url": "http://localhost:61498/?blocklet=afs-preview-fixture", "label": "(Safari / universal)" } ] }, "build": { "id": "2.0.0-beta.48+5a5316bde (debug)", "exec": "/path/to/arc/runtimes/node/dist/cli.mjs" }, "live": { "ok": true, "url": "http://127.0.0.1:61498/.well-known/arc/instance", "record": { "version": "2.0.0-beta.48", "commit": "5a5316bde", "branch": null, "sha": null, "checkout": "/tmp/arc-svc-docs-514/project", "pid": 95666, "port": 61498, "blocklets": 1 } } } ``` Field groups: the first ten keys are the instance record; `version` … `urls` come from the registry row; `logFile` … `build` are what the human view printed; `live` / `drift` are the reconciliation against the running daemon. `lan` appears instead of nothing when the instance is bound to a non-loopback address, and carries the whole LAN diagnostic as `lines`. `list` reports the record keys for every instance and omits the printed-facts keys — it prints no banner per row and does not probe. Note `sha` is populated here (a real git checkout) where the single-instance example above had `null` (a checkout with no `.git`) — both are real, from two different runs: ```bash $ arc service list --json { "instances": [ { "name": "docs514a", "id": "b719db414c5cc624", "status": "up", "port": 61497, "url": "http://127.0.0.1:61497", "home": "/tmp/arc-svc-docs-514/home-a", "spaceRoot": "/tmp/arc-svc-docs-514/home-a/.afs/spaces", "blocklets": [], "pid": 95665, "version": "2.0.0-beta.48", "commit": "5a5316bde", "branch": null, "sha": "5a5316bdece751ee90416382b3ad851e565afa22", "checkout": "/tmp/arc-svc-docs-514/project", "startedAt": "2026-09-10T01:49:44.207Z", "urls": { "ui": "http://127.0.0.1:61497/", "blocklets": {} }, "host": "localhost", "advertise": true, "uptime": "5s" } ] } ``` `version` on every `list` row is the binary each instance is actually running — a quick way to see which instances an upgrade did not reach. ```bash $ arc service stop --instance docs514b --json { "name": "docs514b", "id": "b719db414c5cc625", "stopped": true, "pid": 95700 } $ arc service delete --instance docs514b --json { "name": "docs514b", "removed": true, "home": "/tmp/arc-svc-docs-514/home-b" } ``` `--view json` is the same channel as `--json`. `logs` is a stream and refuses `--json` — same 0-byte-stdout / stderr shape as every other reject: ```bash $ arc service logs --instance docs514a --json $ echo $? 1 ``` stderr: `ERROR: logs is a stream and does not support --json` yargs-level errors (unknown verb, missing required argument) also print no JSON even with `--json` — they never reach the point where `--json` would matter, and they print the subcommand's help on stderr instead (see [Failures](#failures)). ## Failures Starting an instance that is already `up` (exit `1`). The hint now names the `--home` you started it with, not just the bare verb, because `restart` needs it too when `--home` was passed at start time: ```bash $ arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b ERROR: instance "docs514b" is already running pid 95666, port 61498, started 39s ago use `arc service restart --instance docs514b --home /tmp/arc-svc-docs-514/home-b` or pick another name ``` `restart --port` (and the other config-only flags — see [Flags](#flags) for which ones and why `--home` is different) (exit `1`): ```bash $ arc service restart --instance docs514b --port 4910 ERROR: restart does not reconfigure. use `stop` then `start` to change --port ``` `--space-root` must already be a DID Space: ```bash $ arc service start --instance docs514c --home /tmp/arc-svc-docs-514/home-c \ --space-root /tmp/arc-svc-docs-514/not-a-space ERROR: /tmp/arc-svc-docs-514/not-a-space is not a DID Space. create it with `arc space init` ``` Unknown verb (exit `5`). yargs treats it as "not enough / wrong positional", prints the group's `--help` (shown in full under [`--help`](#help)) on stderr, and both together are prefixed once: ```bash $ arc service foo ERROR: Invalid values: Argument: action, Given: "foo", Choices: list, start, stop, restart, status, delete, gc, url, logs arc service Manage AFS background service Commands: arc service list List every local instance with its status, port and home [aliases: ls, ps] ... ``` `arc service` with no verb at all is the same mechanism, different reason (exit `5`): ```bash $ arc service ERROR: Not enough non-option arguments: got 0, need at least 1 arc service ... ``` A leftover positional instance name (the verb, then a bare name, no `--instance`) is rejected on every verb, including `list` / `gc` — same mechanism again, this time printing the *subcommand's* own `--help` (exit `5`): ```bash $ arc service status somename ERROR: positional instance name was removed; use `--instance ` / `-i` arc service status Report whether an instance is running, and on which port ... ``` ## Removed and retired These used to be documented. They are gone: | Old | Now | | --- | --- | | `arc service [op] [dir] [options]` | `arc service [options]` | | `arc service [name]` | `arc service --instance ` / `-i` | | `--blocklet-dir` | `--blocklet` (parent or single dir) | | `--save` | Recorded automatically on the instance | | `ARC_BLOCKLET_DIR` | Gone. Pass `--blocklet` | | `arc service blocklet-dir add/list` | Gone | | `arc service restart --port 4900` | `restart` refuses config flags | | `ARC_HOME` | **Retired.** Warns and ignores | Genuinely-removed flags no longer get a bespoke error — they now hit yargs' own unknown-argument handler, which offers a "Did you mean?" suggestion and dumps the subcommand's `--help`: ```bash $ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a --blocklet-dir /tmp/nope ERROR: Unknown arguments: blocklet-dir, blockletDir Did you mean? --blocklet arc service start ... $ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a --save ERROR: Unknown argument: save arc service start ... ``` `ARC_HOME` is unaffected by the subcommand split — the warning still fires, still on its own line before the banner, and is not `ERROR: `-prefixed (it is a warning, not a `fail()`, so ArcBlock/arc#6301's unification does not touch it): ```bash $ ARC_HOME=/tmp/retired-home arc service list warning: ARC_HOME is ignored; instance root comes from the service name and --home, not env ``` ## `--help` The group-level `--help` — this is what an unknown verb also dumps (see [Failures](#failures)): ```text arc service Manage AFS background service Commands: arc service list List every local instance with its status, port and home [aliases: ls, ps] arc service start Start an instance, creating it on first use arc service stop Stop a running instance, keeping its record and data arc service restart Restart an instance from its recorded config (does not reconfigure — stop then start for that) arc service status Report whether an instance is running, and on which port arc service delete Delete an instance: its record and its data [aliases: rm, remove] arc service gc Drop registry records whose process is gone [aliases: prune] arc service url Print an instance's base URL (and its blocklets') arc service logs Print an instance's daemon log [aliases: log] Options: --json Output in JSON format [boolean] --view Output view format (json is equivalent to --json). llm is accepted globally; commands without an llm renderer fail closed (declare ⇒ execute; arc#6037). [string] [choices: "default", "llm", "human", "json"] [default: "default"] --home Instance root — to pick which instance, use --instance. Used by `arc service start` (create) and `arc did init` (identity). In `--standalone`, sets DID Space and configDir; mounts come from a cwd-walk of `.afs-config/config.toml`, not from --home. [string] -i, --instance Named local ARC instance this command operates against (see `arc service list`). Omit for the default instance. [string] --print Print one result field (e.g. url, port) as plain text — not a view; overrides --json/--view [string] -h, --help Show help [boolean] -v, --version Show version number [boolean] Examples: arc service list Show every local instance arc service start -i alice Start (or create) named instance alice arc service status -i alice Is alice running, and on which port? arc service logs -i alice Print alice's recent daemon logs arc service stop -i alice Stop alice without deleting it arc service delete -i alice --dry-run Preview deleting instance alice without removing it ``` Two of the nine subcommands' own `--help` — `start` (the widest flag set) and `delete` (the one with a destructive-verb flag trio) — to show the shape the other seven follow: ```text arc service start Start an instance, creating it on first use Options: --json Output in JSON format [boolean] --view Output view format (json is equivalent to --json). llm is accepted globally; commands without an llm renderer fail closed (declare ⇒ execute; arc#6037). [string] [choices: "default", "llm", "human", "json"] [default: "default"] --home Instance root — to pick which instance, use --instance. Used by `arc service start` (create) and `arc did init` (identity). In `--standalone`, sets DID Space and configDir; mounts come from a cwd-walk of `.afs-config/config.toml`, not from --home. [string] -i, --instance Named local ARC instance this command operates against (see `arc service list`). Omit for the default instance. [string] --print Print one result field (e.g. url, port) as plain text — not a view; overrides --json/--view [string] --port Port to listen on (0-65535). 0 = auto-assign. Omit: default uses 4900; named instances use the recorded port or auto-assign [number] --host Bind address (localhost, 0.0.0.0, ::, or a unicast IP) [string] [default: "localhost"] --advertise Advertise this instance over mDNS when bind is non-loopback (use --no-advertise to disable) [boolean] [default: true] --blocklet Blocklet-parent or single-blocklet dir to serve (repeatable). Recorded on the instance. [array] --space-root Folder-as-DID-Space created with `arc space init` (omit to derive from home) [string] -h, --help Show help [boolean] -v, --version Show version number [boolean] Examples: arc service start -i alice Start (or create) named instance alice arc service delete Delete an instance: its record and its data Options: --json Output in JSON format [boolean] --view Output view format (json is equivalent to --json). llm is accepted globally; commands without an llm renderer fail closed (declare ⇒ execute; arc#6037). [string] [choices: "default", "llm", "human", "json"] [default: "default"] --home Instance root — to pick which instance, use --instance. Used by `arc service start` (create) and `arc did init` (identity). In `--standalone`, sets DID Space and configDir; mounts come from a cwd-walk of `.afs-config/config.toml`, not from --home. [string] -i, --instance Named local ARC instance this command operates against (see `arc service list`). Omit for the default instance. [string] --print Print one result field (e.g. url, port) as plain text — not a view; overrides --json/--view [string] --force Stop a running instance before deleting it [boolean] [default: false] --dry-run Print what would be removed without deleting it [boolean] [default: false] --yes Skip the TTY confirmation prompt [boolean] [default: false] -h, --help Show help [boolean] -v, --version Show version number [boolean] Examples: arc service delete -i alice --dry-run Preview deleting instance alice without removing it ``` The remaining seven (`stop`, `restart`, `status`, `gc`, `url`, `logs` plus the group's own `list`) follow the same shape as `start`/`delete` above minus the flags this page's [Flags](#flags) table already scopes to `start`/`delete`/`logs` — `logs` adds only `--follow`. `--json`, `--view`, `--home`, and `--instance` / `-i` are global (declared once, apply to every `arc` command). `--home` is the instance root; to pick which instance, use `--instance`. See [Overview](../overview/). --- ## arc skill URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-skill/ `arc skill` is the CLI surface for **bundled ARC how-to booklets** (sometimes called L0): list them, print one, or copy them into host agent skill directories (`.agents/skills`, `.claude/skills`). It is **not** (yet) a full agent-skill package manager like [`gh skill`](https://cli.github.com/manual/gh_skill), and it does **not** inventory skills that live only under live AFS mounts (`/{mount}/.skills`). Those remain AFS paths (`arc afs ls` / `read` / `exec`). See the engineering post [What arc skill is today](/en/articles/arc-cli-skill-catalog/) for the three-layer map and open design gap ([arc#1398](https://github.com/ArcBlock/arc/issues/1398)). Booklets are short, offline-safe. After a daemon is up, **live AFS** (`arc afs ls` / `explain` / `read /.knowledge`) is the source of truth for mounts and actions. Booklet text must not invent paths the live tree does not have. Requires a CLI build that includes the `skill` command (from ARC `2.0.0-beta.30` / epic [#3595](https://github.com/ArcBlock/arc/issues/3595) onward). Check with `arc --help | grep skill` or `arc skill --help`. **Usage** ```bash arc skill arc skill list arc skill show arc skill show all arc skill install arc skill install all ``` `arc skill` with no subcommand is the same as `arc skill list`. ### Global options (all skill subcommands) | Option | Meaning | |--------|---------| | `--json` | structured JSON instead of default text | | `--view ` | rendering style for command **output** (not `--help`); `json` is equivalent to `--json` | | `--instance ` / `-i` | which local ARC instance this runs against; omit for `default` (global, see [Overview](../overview/)) | | `--home ` | instance root (global). To pick which instance, use `--instance` | | `-h`, `--help` | help for this command or subcommand | | `-v`, `--version` | CLI version | `--yaml` was removed (advertised on `--help` but never implemented); use `--json` or `--view json`. --- ## list Print the skill index: names, one-line descriptions, and how to obtain a booklet. ```bash arc skill list # same: arc skill ``` - **`--source `** (default `bundled`): where to list from — `bundled` is the L0 booklets shipped with this CLI, `host` reads `.agents`/`.claude` skill dirs already on this machine, `afs` reads mounted providers' `.skills` roots via the live AFS (daemon if running, else ad-hoc), `all` is the union of the three **Example (text, abbreviated)** ```text ARC skill index (L0 bootstrap — not a full manual) Skills: daemon Start, attach, and check the ARC daemon / service without breaking a live session. afs Use AFS paths via `arc afs` (list/read/write/exec/explain) once a world is available. blocklet Discover, scaffold, build, and inspect Arc blocklets via `arc blocklet` without reading the monorepo. mcp Connect MCP clients (`arc mcp`) and explore the live AFS tool surface. How to obtain: • Prefer per-name load: arc skill show • Avoid full dump unless needed: arc skill show all • Install into host agent dirs (when available): arc skill install • After a daemon is up, explore live AFS paths — this catalog is L0 bootstrap only Commands: ... ``` **Example (JSON)** ```bash arc skill list --json ``` ```json { "kind": "index", "skills": [ { "name": "daemon", "description": "Start, attach, and check the ARC daemon / service without breaking a live session." }, { "name": "afs", "description": "Use AFS paths via `arc afs` (list/read/write/exec/explain) once a world is available." }, { "name": "blocklet", "description": "Discover, scaffold, build, and inspect Arc blocklets via `arc blocklet` without reading the monorepo." }, { "name": "mcp", "description": "Connect MCP clients (`arc mcp`) and explore the live AFS tool surface." } ], "howTo": [ "Prefer per-name load: arc skill show ", "Avoid full dump unless needed: arc skill show all", "Install into host agent dirs (when available): arc skill install ", "After a daemon is up, explore live AFS paths — this catalog is L0 bootstrap only" ] } ``` The set of names is whatever this CLI build ships. Do not hardcode the list in agent memory across versions—run `list` again after an upgrade. --- ## show Show one booklet body, or every booklet at once. ```bash arc skill show arc skill show --name arc skill show all ``` | Argument / option | Required | Meaning | |-------------------|----------|---------| | `` or `--name` | yes | skill id from the index, or `all` | Prefer **one name**. `show all` concatenates every booklet (on the order of ~10KB of text in current builds)—use it only when you intentionally want a full dump. **Example** ```bash arc skill show daemon ``` ```text --- name: daemon description: Start, attach, and check the ARC daemon / service without breaking a live session. --- # ARC skill: daemon ... ``` **Errors** Unknown name fails closed with the known list: ```bash arc skill show not-a-skill ``` ```text ERROR: unknown skill 'not-a-skill'. Known: daemon, afs, blocklet, mcp. Prefer: arc skill list ``` --- ## install Copy a booklet (or every booklet) into host agent skill directories as `SKILL.md`. Offline; overwrites if the target already exists. ```bash arc skill install arc skill install --name arc skill install all ``` | Argument / option | Required | Meaning | |-------------------|----------|---------| | `` or `--name` | yes | skill id from the index, or `all` | **Paths written** (under the current working directory): - `.agents/skills//SKILL.md` - `.claude/skills//SKILL.md` **Example** ```bash mkdir -p /tmp/demo-agent && cd /tmp/demo-agent arc skill install afs ``` ```text Installed afs (2 file(s)) Policy: overwrite — same source as `arc skill show`; no second body tree /tmp/demo-agent/.agents/skills/afs/SKILL.md /tmp/demo-agent/.claude/skills/afs/SKILL.md ``` Body matches `arc skill show afs` (modulo a trailing newline). Re-run `install` after CLI upgrade to refresh installed skills. --- ## Built-in booklets (current shipping set) | Name | Role | |------|------| | `daemon` | Start/attach/status for the ARC service without thrashing a live session | | `afs` | Path ops + discover protocol + UI/WM multi-terminal samples | | `blocklet` | `arc blocklet` discover / scaffold / build without reading the monorepo | | `mcp` | Bridge MCP clients into live AFS | After `daemon` + a running service, continue with live AFS: ```bash arc service status # start only if needed — see arc skill show daemon arc afs ls / arc afs explain / arc afs read /.knowledge ``` `/.knowledge` leads with an **Agent bootstrap** section on live daemons. Prefer that over memorizing mount tables. --- ## Related - [arc service](/en/docs/arc-cli/command-reference-service/) — background daemon lifecycle - [arc afs](/en/docs/arc-cli/command-reference-afs/) — path operations after the world is up - [arc mcp](/en/docs/arc-cli/command-reference-mcp/) — MCP bridge - [arc blocklet](/en/docs/arc-cli/command-reference-blocklet/) — package lifecycle --- ## arc space URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-space/ `arc space` manages local DID Space data, the per-app, per-user storage that backs DID Space. Ten user-facing subcommands: three read, one moves data, one deletes, five manage a folder-backed space — plus an eleventh, internal one; see [`sync-bench`](#sync-bench-internal) at the bottom of this page. Captured against `arc` `2.0.0-beta.48`, commit `5a5316bde` (main, 2026-09-10) — pinned to the commit, not the semver: a second build has carried the same `2.0.0-beta.48` string. Run `arc --version` before you copy dumps. ```bash arc space [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). The inspection subcommands (`list`, `tree`, `path`, `rm`) take `--scope` to pick which DID Space to operate on, plus `--root-path`/`--user-did` to override where that data lives. Only `list` accepts `--scope all`; `tree`, `path` and `rm` take `instance|user`. The folder subcommands (`init`, `check`, `repair`, `set`, `migrate`, and `sync`) address a directory directly — a path already says which space it belongs to. **Every subcommand's default (non-TTY) view is its own** — this page's own drift, found while recapturing it: `list`'s default already is the full human-readable block shown below; `check` and `migrate` default to **JSON**, not text; `sync` defaults to a condensed one-line-per-rejection summary, not the long-form explanation. `--view human` is the one view that is stable and consistent across every subcommand, and it is what every prose example on this page uses from here on — pass it explicitly rather than relying on the default, which differs by subcommand and is not this page's contract. `--json` is unaffected by any of this — it is always the full structured payload. In the examples below, the demo space path is shortened to `~/notes`; everything else is copied verbatim from a real run. ## Inspecting what's stored ### arc space list List app spaces with their file counts and roots. **Usage** ```bash arc space list [options] ``` - **`--scope `**: which DID Space to operate on (default `all`) - **`--root-path `**: root path for DID Space storage, overrides config - **`--user-did `**: user DID, overrides config; the root path falls back to the config default - **`--all`**: show all entries (default caps at 100) With no app spaces under the root, `list` prints one block per scope (`Instance DID Space` and `User DID Space`), each saying `(no app spaces)` — there is no single-line "nothing here" empty state; every response is scope-shaped: ```bash $ arc space list --root-path ~/spaces Instance DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G Root: ~/spaces (no app spaces) User DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G Root: ~/spaces (no app spaces) ``` With at least one app present, each block gets a small table instead of `(no app spaces)`: ```bash $ arc space list --root-path ~/spaces --view human Instance DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G Root: ~/spaces DID Files Last Modified ─── ───── ───────────── did:abt:notes-app 0 — User DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G Root: ~/spaces DID Files Last Modified ─── ───── ───────────── did:abt:notes-app 0 — ``` `list`'s default (non-TTY) view is already this same human-readable, per-scope block — it is the one subcommand on this page where `--view human` changes nothing. `--json` carries the same two groups as a `groups` array, each with `role`, `userDid`, `rootPath`, `apps`, and `total`. ### arc space tree Show the file tree for one app space. **Usage** ```bash arc space tree [options] ``` - **`--app-did `** (required, also the first positional): app DID to inspect - **`--scope `**: which DID Space (default `instance`) - **`--path `**: path inside the app fragment (default `/`) - **`--depth `**: maximum tree depth (default `99`) - **`--limit `**: maximum entries, unless `--all` (default `100`) - **`--all`**: show all entries, ignores `--limit` - **`--root-path `** / **`--user-did `**: same overrides as `list` `--app-did` must be given positionally — `arc space tree --app-did ` alone, with no positional, is refused as a missing argument even though `--app-did` also appears in the flag table above and in `--help`'s `Options:` list. `tree` on an app DID with no space at all is a real reject (exit `5`, `App space not found: `) — the accept-path counterpart is [`arc space path`](#arc-space-path) just below, which answers the same missing DID without erroring, because it only computes where the data *would* live. ### arc space path Print the AFS path for an app DID Space fragment, useful when you want to feed it into `arc afs` commands directly. **Usage** ```bash arc space path [path] [options] ``` - **`--app-did `** (required, also the first positional): app DID to inspect - **`--scope `**: which DID Space (default `instance`) - **`--path `**: path inside the app fragment (default `/`) - **`--root-path `** / **`--user-did `**: same overrides as `list` Unlike `tree`, `path` does not require the app space to actually exist — it prints the computed AFS path regardless, exit `0`: ```bash $ arc space path did:abt:no-such-app --root-path ~/spaces /spaces/z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G/blocklets/no-such-app/system ``` ## Moving data ### arc space sync Move data between two subtrees — local folders, remote hosts, or one of each. Makes `--to` converge toward `--from`. This is the one command for "move data from A to B", in either direction and between any two ends. Direction and both ends are arguments, never the command name — to pull instead of push, swap `--from` and `--to`. It addresses spaces by path, which is why it has no `--server`, `--app-did` or `--scope`: a `layout=files` space puts real directories on disk, so a path already says which space and which fragment you mean. (`--scope` still applies to `list`/`tree`/`path`/`rm`, which address a space by DID.) Global `--instance` / `-i` still picks which local ARC instance the command talks to; it is not a DID Space id. **Usage** ```bash arc space sync --from --to [options] ``` Each `` is either a local folder or `https://[/]` for a remote app's user fragment. The two forms are told apart by scheme alone, so a mistyped URL is never silently reinterpreted as a relative directory name. - **`--from `** (required): source - **`--to `** (required): destination - **`--mirror`**: delete destination-only files (default: additive, nothing is removed) - **`--dry-run`**: report the differences without writing anything - **`--engine `** (default `auto`): force an engine. `auto` negotiates the strongest one both ends support. A named engine that is unavailable is an **error**, never a silent downgrade - **`--verify`**: after syncing, recompute every destination file's CID against the source. Combined with `--dry-run` it *asserts* the destination already matches, exiting non-zero if not - **`--full`**: ignore any recorded cursor and re-read everything — no cursor, and no reading either end's index; both trees are walked directly. The first sync into a destination is full either way; use this to rebuild a destination you no longer trust, or to sync a claimed folder that is deliberately written outside AFS (whose index is expected to lag, and which otherwise fails with an index-diverged error — see the note after the third example below) - **`--init`**: claim a folder destination as `layout=files` (default when the source is claimed) - **`--external-writes `** (default `possible`): query-freshness declaration for a claimed destination, only consulted when the destination is actually claimed - **`--token `**: access token for a remote endpoint, an alternative to browser auth - **`--browser`**: open a browser for the auth flow (default `true`); pass **`--no-browser`** with `--token` for unattended runs Every run below also prints a short progress trace on stderr (`Scanning source N files, destination M (…ms) / Comparing (…ms) / Syncing X/Y (…ms) / Total: …ms`, omitted from the stdout dumps below) and a `File list:` line stating whether each side answered from an index snapshot or fell back to a scan — neither is documented elsewhere on this page, so both are new since the last capture. **Additive by default.** A first sync reports what it moved, and names the engine it negotiated along with why the others were rejected. `--view human` gives the long form of each rejection reason; the default (non-TTY) view gives a one-line summary instead — see the note above [Inspecting what's stored](#inspecting-what-s-stored) for why this page uses `--view human` throughout: ```bash $ arc space sync --from src --to dst --view human src → dst Base path: / Mode: additive Engine: manifest — the manifest engine works between any two endpoints not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it not cursor: the cursor engine mirrors (it deletes destination-only paths); this run is additive, so use --mirror to allow deletions or let the manifest engine handle it File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot) Added: 2 Modified: 0 Deleted: 0 Unchanged: 0 Transferred: 2 files Verified: no Duration: 348ms ``` `src`/`dst` here are two plain, never-`arc space init`-ed folders — that is why `File list:` says `scan (Operation not supported: paginated snapshot)` for both: neither side has an index to snapshot from, so the manifest engine falls back to walking the tree directly. Files that exist only in the destination are left alone. Pass `--mirror` when you want the destination to become an exact copy — this second run also removed `b.txt` from `src` first, so `Deleted: 1` reflects a real removal, not a contrived number: ```bash $ arc space sync --from src --to dst --mirror --view human src → dst Base path: / Mode: mirror (deletes destination-only files) Engine: manifest — the manifest engine works between any two endpoints not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it not cursor: source is not a claimed DID Space, so it keeps no changelog ledger to take a cursor from File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot) Added: 0 Modified: 0 Deleted: 1 Unchanged: 1 Transferred: 0 files Verified: no Duration: 322ms ``` When the **source** is itself a claimed `layout=files` space (`arc space init`), the same rejection reads differently — this is the wording worth remembering, because it names the actual remedy: ``` not cursor: source is layout=files with externalWrites="possible" — the changelog cannot see edits made outside AFS; run `arc space set external-writes=none` (only if the folder really is exclusively AFS-managed) to enable cursor-incremental sync File list: source snapshot, destination snapshot ``` (Real capture, claimed source/destination — `File list:` now says `snapshot` on both sides with no fallback reason, because both have an index to read from.) **`--dry-run` shows, `--verify` asserts.** Together they check a destination without touching it — the run below found one tampered file and exited `1`: ```bash $ arc space sync --from src --to dst --dry-run --verify --view human src ⇢ (dry-run) dst Base path: / Mode: additive Engine: manifest — the manifest engine works between any two endpoints not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it not cursor: the cursor engine mirrors (it deletes destination-only paths); this run is additive, so use --mirror to allow deletions or let the manifest engine handle it File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot) Added: 0 Modified: 1 Deleted: 0 Unchanged: 0 Transferred: 0 files Verified: no Duration: 357ms ``` `--dry-run` needs both ends to exist already; only a real run creates the destination directory. **New since the last capture: `--dry-run --verify` against a *claimed* destination that was hand-edited outside AFS refuses outright, rather than reporting the drift as `Modified`** — `--help`'s own text for `--full` names this exact failure: ``` $ arc space sync --from src-claimed --to dst-claimed --dry-run --verify --view human ERROR: Provider "did-space-files" cannot reach its "query-freshness" dependency at "/": index has diverged from disk in 1 directory — /: a.txt (size-mismatch) — run `arc space repair --folder dst-claimed` to repair. Or re-run with --full to read both trees directly and ignore the indexes (slower, but it is the right choice for a folder that is deliberately written outside AFS). ``` (exit `5`.) Passing `--full` (or running `arc space repair --folder ` first) is the accept-path counterpart — same tampered file, same command, one flag added, and it reports `Modified: 1` and exits `1` (the `--verify` mismatch exit, not a refusal) exactly like the plain-folder example above. ## Editing ### arc space rm Delete a file or directory, recursively, inside a local app space. It goes through the space's ledger — a bare `rm -rf` leaves the index with a phantom row that only `arc space repair` clears. **Usage** ```bash arc space rm [options] ``` - **`--app-did `** (required, also the first positional): target app DID - **`--path `** (required, also the second positional): path inside the app fragment - **`--scope `**: which DID Space (default `user`) - **`--root-path `** / **`--user-did `**: same overrides as `list` Both positionals are required — `arc space rm ` alone (no path) is refused as "not enough non-option arguments", the same yargs-level guard `tree`/`path` hit above for a missing `--app-did`. ## Folder spaces A claimed folder is a DID Space backed by a plain, hand-editable file tree plus a `.did-space/` index, as opposed to the `layout=cas` (content-addressed) form. These five commands claim a folder, check whether its index still agrees with disk, rebuild it when it doesn't, and convert a CAS space to the folder form. ### arc space init Initialize a folder as a writable DID Space — creates `.did-space/` only. **Usage** ```bash arc space init [options] ``` - **`dir`** (required): folder to claim as a DID Space (a ledger, when `--source` is set) - **`--external-writes `** (default `possible`): query-freshness declaration for the new space. `possible` — a human-initialized folder can always be hand-edited, so every query re-scans disk. `none` — pass only when something else (a daemon) will manage this folder exclusively; queries then answer straight from the index. The external-ledger form (`--source`) requires `possible` - **`--source `**: read-only truth layer for the external-ledger form; the ledger (`.did-space/config` + `space.db`) is created at `dir`, the source itself is never written ```bash $ arc space init ~/notes Initialized DID Space at ~/notes (layout=files, externalWrites=possible) ``` `init`'s default view is this same one-line text; `--json` gives `{ "dir", "layout", "externalWrites" }`. Claiming a folder that already has files in it does **not** index them — `init` only creates `.did-space/`. Run `arc space repair --folder ` afterwards, or `arc space check --folder ` first to see what the index is missing. ### arc space check Audit local DID Spaces: layout (migrated / needs migration / unreadable) and index-vs-disk freshness. Read-only — it never writes the index or the config. Exits non-zero when anything needs migrating, cannot be read, or has drifted. **Usage** ```bash arc space check [options] ``` - **`--folder `**: check exactly one claimed folder's freshness, skipping the layout sweep entirely - **`--root `** (repeatable): root directory for the layout sweep. Default: this instance's space root **and** its sibling `/.afs/work` — the host work ledger lives there, outside `root_path`, and a sweep that misses it reports a false all-clear - **`--root-path `**: root path override for the sweep **`check`'s default (non-TTY) view is JSON**, not the text below — this is new since the last capture on this page, which showed the text as if it were the default. Every example below passes `--view human` for the readable form; drop it and you get the same data as `{ "folder", "layout", "externalWrites", "directoriesChecked", "fresh", "dirty" }` instead (identical payload whether you ask via the default view or `--json` explicitly). Drift is reported per directory, with the remedy spelled out: ```bash $ arc space check --folder ~/notes --view human Check freshness: ~/notes (layout=files, externalWrites=possible) Directories checked: 2 Result: DRIFT DETECTED — 2 of 2 directories disagree with disk / ! b.txt [missing-in-index] ! notes [missing-in-index] /notes ! a.md [missing-in-index] Run `arc space repair --folder ~/notes` to repair (review the entries above first — it rebuilds the WHOLE index from disk). ``` A clean space says so and exits `0`: ```bash $ arc space check --folder ~/notes --view human Check freshness: ~/notes (layout=files, externalWrites=possible) Directories checked: 2 Result: CLEAN — index agrees with disk ``` ### arc space repair Repair a claimed folder space by rebuilding its index from the real file tree. Use it after hand-editing files under a claimed folder, or after a bare `rm -rf` inside one. **Usage** ```bash arc space repair --folder [options] ``` - **`--folder `** (required): claimed folder to repair (must be `layout=files`) - **`--index`** (default `true`): rebuild the folder-backend index from disk — the only repair this command performs today ```bash $ arc space repair --folder ~/notes Repaired index for ~/notes (layout=files) Added: 2 Modified: 0 Deleted: 0 Unchanged: 0 Duration: 43ms ``` `repair`'s default view is this same text; `--json` gives `{ "folder", "layout", "added", "modified", "unchanged", "deleted", "elapsed" }` (note `elapsed`, not `Duration` — the two views use different key names for the same number). ### arc space set Set a declaration on an *existing* `layout=files` DID Space. **Usage** ```bash arc space set ``` - **`--folder `** (required, also the first positional): claimed folder to update (must already be `layout=files` — see `arc space init`) - **`--assignment =`** (required, also the second positional): the declaration to set. `external-writes=none` — this folder is under exclusive (e.g. daemon) management, so queries answer straight from the index with no disk scan. `external-writes=possible` — the folder can still be hand-edited, so a query re-scans disk before every answer. Idempotent and reversible either direction; every other key already in `.did-space/config` is preserved untouched ```bash $ arc space set ~/notes external-writes=none Set externalWrites=none for ~/notes (layout=files) ``` ### arc space migrate Migrate a `layout=cas` DID Space in place to `layout=files` (copy → verify → atomic replace; the old CAS directory is kept for rollback). **Usage** ```bash arc space migrate --to-layout files [options] ``` - **`dir`** (required): claimed DID Space folder to migrate (must be `layout=cas`) - **`--to-layout `** (required): target layout — only `files` is supported - **`--dry-run`**: report what would happen (space count, file count, byte count, expected result) — zero disk changes - **`--external-writes `** (default `none`): query-freshness declaration for the resulting `layout=files` space. Default `none` because a `layout=cas` space's truth layer (`objects/` + `_metadata.db`) isn't something a human hand-edits, so "no external writer at migration time" is an assertable fact; pass `possible` only if this space has actually been treated as a plain hand-editable folder **`migrate`'s default (non-TTY) view is JSON too**, same as `check`; `--view human` gives a short sentence-form summary instead. Migrating a folder that is **already** `layout=files` is not an error — it is a real, idempotent accept path, exit `0`: ```bash $ arc space migrate ~/notes --to-layout files --view human Migrate ~/notes (layout=cas -> layout=files) Already layout=files — nothing to migrate. External writes: none ``` Running `arc space migrate` on a folder with no `.did-space/` at all *is* an error — a different one than "already migrated" above (exit `5`): ```bash $ arc space migrate ~/plain-dir --to-layout files ERROR: arc space migrate: ~/plain-dir is not a claimed DID Space (no .did-space/). Run `arc space init ~/plain-dir` first. ``` Rollback if a migration needs to be undone: ```bash rm -rf "" mv "/.cas-backups/" "" ``` The pre-migration `layout=cas` directory is kept at `/.cas-backups/` and is never deleted automatically. It deliberately sits one level below the space's own parent, in a container that is not itself a claimed space, so space enumeration — and therefore daemon boot — never rediscovers the backup. ## `sync-bench` (internal) An eleventh subcommand exists on this build: `arc space sync-bench`, a SyncEngine throughput benchmark driven over `afs-rpc` (the `afs-rpc-batch` P6 driver). It requires `--server ` and `--token ` — a real remote endpoint, not a local folder — and seeds/benchmarks/cleans up throwaway files under a `--prefix` (default `e2e-batch/bench`). It has no read/write/inspect role in a space's data model the way the other ten do; see `arc space sync-bench --help` for its flags (`--blocklet`, `--files`, `--size`, `--single-op`, `--header`, `--cleanup`). Not documented further on this page. --- ## arc upgrade URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-upgrade/ `arc upgrade` upgrades the `arc` binary itself to the latest published release, or to a specific pinned version. **Usage** ```bash arc upgrade [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). - **`--check`**: only check whether an update is available, don't install it - **`--to `**: install a specific version instead of the latest published one - **`--from `**: debug channel — build this local git source tree and swap the running daemon's exec, instead of installing a published tarball - **`--force`**: for the `--from` debug channel only — allow swapping to an older debug build (by default `--from` refuses that downgrade). Plain `--to ` has no such guard: it installs whatever version you name, even an older one, and still reports it as `upgraded` - **`--base `**: tarball host base URL (default `https://dl.arcblock.io`, env `ARC_INSTALL_BASE`) - **`--install-script-base `**: `install.sh` host base URL (default `https://arc.arcblock.io`, env `ARC_INSTALL_SCRIPT_BASE`) - **`--dir `**: install root (default `~/.arc`, env `ARC_INSTALL_DIR`) **Example** ```bash $ arc upgrade --check already up to date (2.0.0-beta.48) ``` If a newer release is published, the message instead reads `update available: → (run 'arc upgrade' to install)`. --- ## arc vault URL: https://www.arcblock.io/en/docs/arc-cli/command-reference-vault/ `arc vault` is encrypted secret storage. Secrets are organized as `group/name`, for example `aws/access-key-id`. ```bash arc vault [options] ``` Global flags (see [Overview](../overview/)): `--json`, `--view`, `--instance` / `-i` (which local ARC instance; omit for `default`), and `--home` (instance root; to pick which instance, use `--instance`). ### arc vault init Initialize a new encrypted vault. **Usage** ```bash arc vault init [options] ``` - **`--vault-path `**: path for the vault file (default `~/.afs-config/vault/vault.enc`). `--path` still works as a deprecated alias for `--vault-path`, but only on this one subcommand — `arc vault get/set/list/delete` all accept `--vault-path` too, but none of them ever accepted `--path` as an alias for it **Example** ```bash $ arc vault init --vault-path ./demo-vault.enc Vault initialized at ./demo-vault.enc Reused the existing master key (AFS_VAULT_KEY or OS keychain) — keep that source available. ``` The master key itself comes from `AFS_VAULT_KEY` or your OS keychain, not from this command, `arc vault init` just points a vault file at whichever key source is available. ### arc vault set Store a secret. **Usage** ```bash arc vault set [options] ``` - **`--group `** (required): secret group, e.g. `aws`, `github` - **`--name `** (required): secret name, e.g. `token`, `access-key-id` - **`--value `** (required): the secret value - **`--vault-path `**: path to the vault file, defaults to the standard location **Example** ```bash $ arc vault set demo api-key sk-example-12345 --vault-path ./demo-vault.enc OK demo/api-key ``` ### arc vault get Read a secret value. ```bash arc vault get [--vault-path ] ``` **Example** ```bash $ arc vault get demo api-key --vault-path ./demo-vault.enc sk-example-12345 ``` ### arc vault list List secrets. Aliased as `arc vault ls`. **Usage** ```bash arc vault list [group] [options] ``` - **`--group `**: secret group to list, omit for all groups - **`--vault-path `**: path to the vault file **Example** ```bash $ arc vault list --vault-path ./demo-vault.enc demo ``` ### arc vault delete Delete a secret or an entire group. Aliased as `arc vault rm`. **Usage** ```bash arc vault delete [name] [options] ``` - **`--group `** (required): secret group - **`--name `**: secret name, omit to delete the entire group - **`--vault-path `**: path to the vault file **Example** ```bash $ arc vault delete demo api-key --vault-path ./demo-vault.enc Deleted demo/api-key ``` --- ## Exit Codes URL: https://www.arcblock.io/en/docs/arc-cli/exit-codes/ Every `arc` command exits with a number you can branch on. Having more than one non-zero value is the whole point: "the path you asked for is not there", "you mistyped the command", and "no daemon is running" want three different responses from a script, and nothing should have to pattern-match on English error text to tell them apart. | Exit code | Meaning | Scope | | --- | --- | --- | | `0` | The command did what you asked | every command | | `1` | Not there — or, for `service start`, already there | every command | | `2` | Permission denied | reserved — no command in this release returns it (see below) | | `3` | The instance is on record but is not running (`stopped`, `starting`) | `arc service status` | | `4` | The instance is recorded as running, but its process is gone (`dead`) | `arc service status` | | `5` | Runtime error, including every usage mistake | every command | | `6` | The command needed a daemon and none was running | every command | | `7` | `--view llm` was requested on a command that has no llm renderer | any command's `--view llm` | **Mind the scope column.** `3` and `4` above are `arc service status`'s own reading of an instance record, not a promise about the whole CLI: elsewhere those two numbers carry the runtime's generic meanings — `3` a conflict, `4` a partial success — and `4` has a live producer, a batch `arc did issue` in which some providers succeeded and others failed. A script that reads `rc == 4` as "the daemon died" will misread that batch. Branch on `4` only for `arc service status`. **`2` is in the enum but has no producer in this release** — the `2` section below shows how that was checked, not assumed. **`7` is scoped narrowly**: it only fires for `--view llm` on the commands that lack an `llm` renderer; every command still accepts `--view default` / `--view json` / `--view human`. Each section below is a real run of the situation it describes, captured against `arc` `2.0.0-beta.48` (commit `5a5316bde`, 2026-09-10). The version number alone will not tell you which build you have — `2.0.0-beta.48` has named more than one binary this cycle — so run `arc --version` and compare its third field, the commit, against the one printed here before trusting any output on this page byte-for-byte. Read the table as "what these codes mean" rather than as the complete set of numbers `arc` can ever return: a command that fails in some way not listed here still exits non-zero, and new codes can appear in later releases. ## `0` — the command did what you asked ```bash $ arc service list NAME ID PORT STATUS HOME SOURCES (no instances) ``` An empty result is still success. Finding nothing to list is not a failure — asking for a *specific* thing that is not there is what gets you `1`. ## `1` — not there, or already there Reading a path that does not exist: ```bash $ arc afs read /no-such-file --instance notes ERROR: No data found for path: /no-such-file ``` Naming an instance that was never created: ```bash $ arc service status --instance nope ERROR: no instance named "nope". `arc service list` shows 1 ``` And — the case worth remembering — starting an instance that is *already* up: ```bash $ arc service start --instance notes ERROR: instance "notes" is already running pid 93652, port 61430, started 15s ago use `arc service restart --instance notes` or pick another name ``` That last one is `1`, not `5`. The code means "what you named was not in the state you needed", which covers both a thing that is missing and a thing that is already there. It is not a usage mistake, so it is not `5`. ## `2` — permission denied, defined but not yet produced The runtime's exit-code enum reserves `2` for `PermissionDeniedError`, and that class exists in the CLI's own error module. Nothing in this release throws it: no command constructs a `PermissionDeniedError`, and a permission failure raised by the AFS layer underneath the CLI is not translated into one — it just keeps propagating as an ordinary error, which lands on `5` like any other unhandled failure. This is checked, not assumed: an unreadable file, made with `chmod 000`, reproduces the real behavior directly. ```bash $ arc afs read /vault/locked.txt --standalone ERROR: EACCES: permission denied, open '/tmp/arc-perm-test/secret/locked.txt' ``` That command exits `5`. Treat `2` as a number the protocol has set aside for a distinction the CLI does not draw today, not as one you will see in practice. ## `3` — the instance exists but is not running ```bash $ arc service stop --instance notes Service stopped: notes $ arc service status --instance notes Instance: notes ID: ab5aa97074c454a0 Status: stopped PID: 93652 Port: 61430 URL: http://127.0.0.1:61430 Home: /tmp/arc-docs-demo/notes Note: PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process. ``` Several fields — `Version`, `Commit`, `Checkout`, `Space`, `Sources`, `Host` and `Started` — are elided above. The pid, port and URL are still reported after a stop, and the `Note:` line says in words that they are historical — in `--json` the same fact is a `lastKnown` marker. `starting` returns `3` as well, which matters if you are writing a wait-for-up loop: `3` means "not ready", not "not coming". On a cold start the window is a few seconds, and a status poll walks `stopped` → `starting` (exit `3`) → `up` (exit `0`). Treat `3` as "keep waiting" and `4` as "stop waiting". ## `4` — recorded as running, but the process is gone No ordinary sequence of commands gets you here, because this code describes damage rather than a choice. To see it, start an instance and kill its daemon outright, so the registry row still claims `up` while the process behind it no longer exists: `start` prints a full status block of its own; the pid you need for the next step is on its `PID:` line. Both blocks below are trimmed to the fields that matter here. ```bash $ arc service start --instance notes --home /tmp/arc-docs-demo/notes Instance: notes Status: up PID: 95288 Port: 61430 Home: /tmp/arc-docs-demo/notes $ kill -9 95288 $ arc service status --instance notes Instance: notes ID: ab5aa97074c454a0 Status: dead PID: 95288 Port: 61430 URL: http://127.0.0.1:61430 Home: /tmp/arc-docs-demo/notes Note: PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process. ``` `dead` is what you get from a crash, an OOM kill, or a reboot — anything that ends the process without going through `arc service stop`. The distinction from `3` is worth having: `stopped` is a state someone chose, `dead` is one nobody chose. `arc service gc` removes records in this state and only this state. ## `5` — runtime error, usage mistakes included This is the broadest code. Every way of getting the command line wrong lands here. Each of the next three also prints the relevant usage text after what you see below — the full command list for the first, that command's own help for the other two. An unknown command: ```bash $ arc serivce list ERROR: Unknown command: "serivce" Did you mean? arc serve arc service ``` an unknown option: ```bash $ arc service list --bogus ERROR: Unknown argument: bogus ``` a missing required argument: ```bash $ arc space rm ERROR: Not enough non-option arguments: got 0, need at least 2 ``` and, past the command line, a request the runtime cannot route: ```bash $ arc afs exec /no-such-action --instance notes ERROR: No module found for path: /no-such-action in namespace 'default' ``` `5` also covers a command that ran correctly and reported a real-world problem — [`arc network doctor`](../command-reference-network/) exits `5` when any of its checks fails. So `5` on its own does not tell you whether you typed something wrong or something out there is broken; that is what the message is for. ## `6` — the command needed a daemon and none was running ```bash $ arc afs ls / ERROR: No AFS daemon is running for instance "default". Start it with: arc service start Or use --standalone for ad-hoc mode (no runtime state) ``` The suggested command on the second line echoes back only the flags you actually typed — omit `--instance` and `--home` and it suggests the bare `arc service start`; pass `--instance foo --home ~/foo` yourself and it suggests exactly that back, never a value you did not type. `6` exists so this case is distinguishable from `5` without reading the message. An unmet precondition you can fix by starting a daemon is a different thing from a command that failed, and the error text names the fix. The same `6` comes back for a named instance whose daemon is `stopped` or `dead`, not only for `default`. ## `7` — `--view llm` was requested, but this command cannot render it `--view llm` is accepted globally, but not every command has an `llm` renderer for it, and an unimplemented one fails closed instead of silently falling back to the default view. `arc network doctor` has no `llm` renderer: ```bash $ arc network doctor --view llm ERROR: --view llm is not implemented for `network doctor`. This command has no llm renderer (declare ⇒ execute; will not silently fall back to default). ``` `arc afs ls` does implement one, and the same flag on a command that supports it succeeds: ```bash $ arc afs ls / --standalone --view llm ENTRY /spaces CHILDREN=-1 DESC="Local DID Space logical roots" ENTRY /peers CHILDREN=-1 DESC="Dispatchable ARC hosts (always includes local)" ENTRY /ash CHILDREN=-1 DESC="ASH pipeline DSL for deterministic data pipelines" ENTRY /dev CHILDREN=-1 ENTRY /modules CHILDREN=-1 ENTRY /team CHILDREN=-1 ENTRY /.knowledge KIND=afs:system CHILDREN=-1 DESC="Provider capability index" ENTRY /.meta KIND=afs:system CHILDREN=-1 DESC="Root metadata and mount info" ENTRY /.actions KIND=afs:system CHILDREN=-1 DESC="Root-level executable actions" TOTAL 9 ``` The distinction that matters for scripts: an unrecognized `--view` value (say, `--view bogus`) is a **usage** mistake caught by argument parsing, and exits `5` like any other bad flag — ```bash $ arc service list --view bogus ERROR: Invalid values: Argument: view, Given: "bogus", Choices: "default", "llm", "human", "json" ``` — while `--view llm` on a command with no `llm` renderer is a **valid, recognized** value that this particular command cannot honor, and exits `7`. Without the split, a script cannot tell "I typed the flag wrong" from "the flag is right but this command doesn't support it yet" without parsing English text either way. --- ## Install URL: https://www.arcblock.io/en/docs/arc-cli/install/ `arc` ships as a prebuilt package for macOS and Linux, on both Intel and Arm. One command installs it: ```bash curl -fsSL https://arc.arcblock.io/install.sh | bash ``` With no version argument the installer resolves the current published release. Pass `--version ` after `bash -s --` only when you deliberately want an older build. The installer downloads the build for your platform, checks it against a checksum published from a second, independent origin, unpacks it under `~/.arc/versions/`, and points `~/.arc/current` at it. On macOS it inspects the code signature as well; a build that is not yet signed with ArcBlock's Developer ID produces a warning and the install continues. Finally it writes a PATH line into your shell profile and prints which file it changed. If the current shell still cannot find `arc`, open a new terminal. ## Confirm what you installed ```bash arc --version ``` Every build prints its version: ```text ``` Newer builds add the short commit they were built from and its build date, as ` () `. Both forms are correct. One version number can cover more than one build, so where you need to be exact about which `arc` you are running, the commit is the field that separates them. Command pages here paste real terminal output. Where yours differs, `arc --help` on your own build is the authority. ## Move to a newer release later `arc upgrade` replaces the installed binary with the current release, and `arc upgrade --check` reports whether a newer one exists without installing anything. See [arc upgrade](../command-reference-upgrade/). With `arc` on your PATH, continue with the [Overview](../overview/) for the flags every command accepts. --- ## Overview URL: https://www.arcblock.io/en/docs/arc-cli/overview/ `arc` is the command line tool for operating an ARC runtime instance. Every top-level command talks to one part of that runtime: `afs` is file system operations, `did` is identity and trust, `vault` is encrypted secrets, `deploy` handles deployment targets, `dsl` works with AUP DSL artifacts, and so on. Version documented here: `2.0.0-beta.48 (5a5316bde)`, built 2026-09-10. `arc --version` always prints this three-field form — ` () ` — because the same `beta.N` string gets reused across different builds; the commit is what actually pins the command surface. Run `arc --version` to check yours; commands and options can change between builds. If `arc` is not on your PATH yet, start with [Install](/en/docs/arc-cli/install/). `arc worker` manages ArcBlock's own Cloudflare deployments. It registers behind two gates that must both hold: a build-time flag that's off in any release build (so the binary you install with `install.sh` never has it), and a runtime check that the current working directory is inside a real `ArcBlock/arc` checkout, or `ARC_WORKER_DIR` is set explicitly (so even a debug build made from that checkout won't show `arc worker` when you run it from somewhere else). It isn't listed below. `arc space sync-bench` is a hermetic benchmark driver for arc's own afs-rpc wire, not a product feature — there's nothing a third party would run it to accomplish with their own data. It registers behind the same build-time flag as `arc worker` (off in any release build), just without `arc worker`'s extra checkout-location check. It isn't listed below either. `arc connect` and `arc explore` were removed: both duplicated things the daemon already does (`arc service start` prints every endpoint including `/explorer`, so there's no separate step to start-and-open). Use `arc service start` instead. ### Global options Every command accepts the same flags: - **`--json`**: print structured JSON instead of the default text output - **`--view `**: pick a rendering style; `llm` is tuned for feeding output back into an agent, `human` for a person reading a terminal, `json` is equivalent to `--json` - **`--instance `** / **`-i`**: which local ARC instance this command operates against (see `arc service list`). Omit for the `default` instance. This is the only name for that axis - **`--home `**: instance root. Used by `arc service start` (create), `--standalone` (ad-hoc), and `arc did init` (identity). To pick which instance, use `--instance` `--json` and `--view` only change how the result prints. They apply to command **output**, not to `--help` itself; help text is always plain text. `--instance` and `--home` change which instance the command talks to. An unrecognized flag is rejected (`ERROR: Unknown argument: `, exit code `5`) — arc does not silently ignore a mistyped or removed option, and help/error text is always in English regardless of your system locale. `--yaml` was one such removed option (advertised on every command's `--help` but never implemented); use `--json` or `--view json` instead. ### When you mistype a command A misspelled top-level command is not simply rejected — `arc` names the commands you probably meant, and then prints the full command list (trimmed after the suggestion here): ```bash $ arc serivce list ERROR: Unknown command: "serivce" Did you mean? arc serve arc service ``` A near-tie offers every candidate rather than guessing between them: `serivce` is one edit away from both `serve` and `service`, so both are printed. Mistyping exits `5`, like any other usage mistake — [Exit Codes](../exit-codes/) covers what each code means. The same mechanism catches a misspelled subcommand or a misspelled option, one level down — always scoped to just that one command's own choices, and always still exit `5`: ```bash $ arc service strat ERROR: Invalid values: Argument: action, Given: "strat", Choices: list, start, stop, restart, status, delete, gc, url, logs Did you mean? arc service start ... $ arc service start --instnace foo ERROR: Unknown argument: instnace Did you mean? --instance ... ``` Fix any of the three and the same command runs normally, exit `0`: ```bash $ arc service list --help arc service list List every local instance with its status, port and home ... ``` ### Previewing a destructive command `--dry-run` is not a global flag. Six commands take one — `arc afs delete`, `arc blocklet build`, `arc deploy`, `arc service delete`, `arc space migrate`, and `arc space sync` — and three take `--yes` to skip a confirmation prompt: `arc afs delete`, `arc service delete`, and `arc did issuer reset` (`afs delete` and `service delete` take both). `arc space sync --dry-run` reports the entire plan and writes nothing (trimmed here to the summary; the engine-selection and timing lines are omitted). ```bash $ arc space sync --from ./src --to ./dst2 --dry-run ./src ⇢ (dry-run) ./dst2 Base path: / Mode: additive Added: 2 Modified: 0 Deleted: 0 Unchanged: 0 Transferred: 0 files ``` `Transferred: 0 files` is the point — the plan says two files would be added, and the destination is still empty afterwards. `arc blocklet build --dry-run` behaves the same way: it prints the manifest it would publish, and leaves no `dist/` behind. Every other command has neither a preview nor a confirmation prompt. **`arc space rm` in particular has neither `--dry-run` nor `--yes`**: it removes a file or directory inside a local app space as soon as you press enter. Look before you delete, with `arc space tree `. ### Command groups ::::card-group ::link-card{title="afs" description="File system operations: ls, read, write, delete, stat, exec, explain, search, subscribe, and mount management." icon="folder"} ::link-card{title="did" description="Identity and trust: generate a DID, issue and verify credentials, manage trusted issuers." icon="fingerprint"} ::link-card{title="vault" description="Encrypted secret storage: init, get, set, list, delete." icon="lock"} ::link-card{title="dsl" description="Validate, lint, format, generate, and inspect AUP DSL artifacts." icon="code"} ::link-card{title="collections" description="Scan content/ and generate the collections: fragment for blocklet.yaml." icon="layers"} ::link-card{title="space" description="Manage local DID Space data: list, tree, path, rm, sync between two subtrees, folder-space claim and repair, folder-layout migration." icon="database"} ::link-card{title="deploy" description="Register a blocklet with the local daemon, or publish it to a DID Space." icon="upload"} ::link-card{title="blocklet" description="Blocklet package and instance lifecycle: scaffold, build, check, deploy, fleet deploy." icon="package"} ::link-card{title="service" description="Manage named AFS background instances: list, start, stop, restart, status, delete, gc, url, logs." icon="power"} ::link-card{title="serve" description="Start a foreground AFS server over HTTP or MCP." icon="globe"} ::link-card{title="attach" description="Reverse-mount a local directory, or this host's HostFace, into a remote arc daemon." icon="plug"} ::link-card{title="drain" description="Long-running: watch the work ledger and dispatch ready work to an idle peer." icon="repeat"} ::link-card{title="mcp" description="Bridge stdio to a running AFS daemon's MCP endpoint." icon="terminal"} ::link-card{title="skill" description="Bundled how-to booklets: list, show, install into host agent skill dirs (not full skill package manager yet)." icon="book"} ::link-card{title="provider" description="Provider package operations: publish a provider's resources to CF Pages." icon="box"} ::link-card{title="upgrade" description="Upgrade arc itself to the latest release, or a pinned version." icon="arrow-up-circle"} ::link-card{title="network" description="Diagnose outbound connectivity: proxy discovery, DNS, HTTPS and WebSocket, each reported separately." icon="wifi"} ::link-card{title="completion" description="Print a bash, zsh, or fish tab-completion script to stdout: command names, subcommand names, instance names, and --recipe values." icon="keyboard"} :::: --- ## ArcBlock Jobs URL: https://www.arcblock.io/en/docs/arcblock/ --- ## ArcBlock Media Kit URL: https://www.arcblock.io/en/docs/arcblock-media-kit/ > **Deprecated.** Current files live on [Media Assets](/en/docs/media-assets/). Keep this URL for history. --- ## AIGNE Logos URL: https://www.arcblock.io/en/docs/arcblock-media-kit/77GaHmpWeDm0sUccOF9k3K1c/ ## All image resources [🗂️ Download AIGNE Logos Media Kit(SVG, PNG) ](https://www.arcblock.io/image-bin/uploads/07f4c546f3aa3aafb37d9c6fd8e9ea01.zip?filename=AIGNE%20Logos.zip) ## AIGNE - AIGNE Logo ![AIGNE logo.png](https://media.arcblock.io/lib/7e/7ee6fde68e201f821dfeb27e08099833.w1600.webp) - AIGNE Logo & Text(Light, Dark) ![AIGNE_light.png](https://media.arcblock.io/lib/e2/e29d59637e993c5bdd7eed0743243647.w1600.webp) ![AIGNE_dark.png](https://media.arcblock.io/lib/db/db5570c77659f589e9ead87a233c7d7d.w1600.webp) --- ## AIGNE Hub - AIGNE Hub Logo ![Hub logo.png](https://media.arcblock.io/lib/32/32acbee4360d587039eab6de1a5de507.w1600.webp) - AIGNE Hub Logo & Text(Light, Dark) ![hub_light.png](https://media.arcblock.io/lib/99/9916119cb56249c0fd960f8613d14664.w1600.webp) ![hub_dark.png](https://media.arcblock.io/lib/19/194efc0ff96ee91c860ae5dfb771e99e.w1600.webp) --- ## AIGNE Studio - AIGNE Studio Logo ![Studio logo.png](https://media.arcblock.io/lib/b4/b4c91d0eb667e8988171188ee28ee786.w1600.webp) - AIGNE Studio Logo & Text(Light, Dark) ![Studio_light.png](https://media.arcblock.io/lib/bb/bb5a69360bee45a8bdbb060080f709f4.w1600.webp) ![Studio_dark.png](https://media.arcblock.io/lib/d9/d9e3aec7c9ef9446b666d4fd7ed4a062.w1600.webp) --- ## AIGNE Framework - AIGNE Framework Logo ![Framework logo.png](https://media.arcblock.io/lib/aa/aa4e6d2472ecf3b65c106e37addc8ea3.w1600.webp) - AIGNE Framework Logo & Text(Light, Dark) ![Framework_light.png](https://media.arcblock.io/lib/49/496b4249f4214dd03073a84052ab7c88.w1600.webp) ![Framework_dark.png](https://media.arcblock.io/lib/ed/eda709e5a26fef15690969b7122fa12c.w1600.webp) --- ## AIGNE CLI - AIGNE CLI Logo ![Cli logo.png](https://media.arcblock.io/lib/ef/ef2885f306752bc618e4d882134c544e.w1600.webp) - AIGNE CLI Logo & Text(Light, Dark) ![CLI_light.png](https://media.arcblock.io/lib/9a/9a08d838108159a4a9d4a93b96a53722.w1600.webp) ![CLI_dark.png](https://media.arcblock.io/lib/0e/0e95f5b03db842d9bbd3aec984c768a4.w1600.webp) --- ## AIGNE Observability - AIGNE Observability Logo ![Obe logo.png](https://media.arcblock.io/lib/8c/8c6819590281dbdfa61bd90821b9a16a.w1600.webp) - AIGNE Observability Logo & Text(Light, Dark) ![Observability logo_light.png](https://media.arcblock.io/lib/cd/cd4551d41d5050e628b083dcedf35614.w1600.webp) ![Observability logo_dark.png](https://media.arcblock.io/lib/5f/5fc291c02bab0abcca789b8bb550c78d.w1600.webp) --- ## AIGNE CodeSmith - AIGNE CodeSmith Logo ![CodeSmith logo.png](https://media.arcblock.io/lib/ef/ef2a984314d9cd97ac7f7b5f8f9035b5.w1600.webp) - AIGNE CodeSmith Logo & Text(Light, Dark) ![CodeSmith_light.png](https://media.arcblock.io/lib/38/38d9f5aff004fa1afd77143692dacde9.w1600.webp) ![CodeSmith_dark.png](https://media.arcblock.io/lib/a4/a451ceb3c2242a384070692f45d6835d.w1600.webp) --- ## AIGNE DocSmith - AIGNE DocSmith Logo ![DocSmith logo.png](https://media.arcblock.io/lib/35/352db97eb4730e0da56ee83fceda718b.w1600.webp) - AIGNE DocSmith Logo & Text(Light, Dark) ![DocSmith_light.png](https://media.arcblock.io/lib/57/57b8904e93eb1f6d98af80df4c262233.w1600.webp) ![DocSmith_dark.png](https://media.arcblock.io/lib/ef/efac0510a143e453d6ad92808be613e4.w1600.webp) --- ## AIGNE WebSmith - AIGNE WebSmith Logo ![WebSmith logo.png](https://media.arcblock.io/lib/c6/c623569a07caf8137952f5811e875a43.w1600.webp) - AIGNE WebSmith Logo & Text(Light, Dark) ![WebSmith_light.png](https://media.arcblock.io/lib/5b/5b6848537697d0ad4e0ada33c887fb9a.w1600.webp) ![WebSmith_dark.png](https://media.arcblock.io/lib/08/089ff947b2c48ce2e490abfd7d19d4cd.w1600.webp) --- ## AIGNE Components - AIGNE Components Logo ![Components logo.png](https://media.arcblock.io/lib/8c/8c195a78b19f87b0ea571b6ca34913fb.w1600.webp) - AIGNE Components Logo & Text(Light, Dark) ![Components_light.png](https://media.arcblock.io/lib/a8/a81eab2f435897090cce09f21b8e1926.png) ![Components_dark.png](https://media.arcblock.io/lib/ba/badf3bb33145daaa6009b78e8b95d0e5.png) --- ## AIGNE Runtime - AIGNE Runtime Logo ![Runtime logo.png](https://media.arcblock.io/lib/da/daaea4cfcbe7e1a4c20064e213d6ff55.w1600.webp) - AIGNE Runtime Logo & Text(Light, Dark) ![Runtime_light.png](https://media.arcblock.io/lib/61/61ccad4e7a6d0b15daddd90d2b3fbace.w1600.webp) ![Runtime_dark.png](https://media.arcblock.io/lib/b2/b22f3f82355065764a96f54b8aced383.w1600.webp) --- ## AIGNE Font - AIGNE Font: [Google Font Link](https://fonts.google.com/?query=Audiowide) ![AIGNE Text.png](https://media.arcblock.io/lib/d6/d6c6c623df088ca95e8b5c7c440484aa.w1600.webp) - AIGNE Series Products Font: [Google Font Link](https://fonts.google.com/specimen/Poppins?preview.text=poppins) ![font.png](https://media.arcblock.io/lib/c7/c76d0a721c931c8acfc320ea07e269b9.w1600.webp) --- ## ArcSphere Logos URL: https://www.arcblock.io/en/docs/arcblock-media-kit/arcsphere-media-kit/ ## All Brand Assets zip [Download ArcSphere Brand Assets ZIP(SVG, PNG)](https://www.arcblock.io/image-bin/uploads/245e8ccce6ac8b003a9973da6d801a69.zip?filename=ArcSphere%20logo.zip) ## ArcSphere Logo & Text ![01.png](https://media.arcblock.io/lib/db/db0b16a2855d006b43e9421b56d8bd07.w1600.webp) ![02.png](https://media.arcblock.io/lib/03/038362c0729229bb6b926a3b54a8dab4.w1600.webp) ![03.png](https://media.arcblock.io/lib/4f/4f866bb3504ec852e913089d2a084dd2.w1600.webp) ![04.png](https://media.arcblock.io/lib/45/450deaf8c773de1953ff7b8dc563e78e.w1600.webp) ![05.png](https://media.arcblock.io/lib/8c/8ce9f7ceb7d445c0630d5aab3c4fdad0.w1600.webp) ![06.png](https://media.arcblock.io/lib/12/12b35f94109f9862ac6149ab7805af0b.w1600.webp) ![09.png](https://media.arcblock.io/lib/45/451156c589e91009972b7d03a0992be7.w1600.webp) ![10.png](https://media.arcblock.io/lib/46/46c6e58160267c0094417cb553bdf76a.w1600.webp) ## ArcSphere Logo ![11.png](https://media.arcblock.io/lib/85/8543578299bec89ecc61ca5c1a5fd977.w1600.webp) ![12.png](https://media.arcblock.io/lib/eb/eb787de0532646e555f8d6be7c890549.w1600.webp) ![13.png](https://media.arcblock.io/lib/26/2694ef28e1a2fdc74e9297b98f347ef5.w1600.webp) ![17.png](https://media.arcblock.io/lib/40/40bd5e3576656510be4e8f1c845502b5.w1600.webp) ## ArcSphere font Logo ![20.png](https://media.arcblock.io/lib/b5/b5cc7c9b09f8a01851c79d102abe5acb.w1600.webp) ![19.png](https://media.arcblock.io/lib/9c/9c9ea6f17e0370217be2af2d3b599429.w1600.webp) ![21.png](https://media.arcblock.io/lib/ab/ab19456a0860a64ccbb9e8c88ddca42a.w1600.webp) ## ArcSphere UI Text ![18.png](https://media.arcblock.io/lib/9f/9fa38916910e610d71335a3dda790c34.w1600.webp) [Download on Google fonts ](https://fonts.google.com/?query=Lexend) --- ## DID Logos URL: https://www.arcblock.io/en/docs/arcblock-media-kit/did-logos/ ## All image resources [🗂 Download ArcBlock DID Logos Media Kit(SVG, PNG)](https://www.arcblock.io/image-bin/uploads/6e0a45195d5c738320ddd19a91615a47.zip?filename=DID%20logos.zip) ## DID - DID Logo ![DID logo@4x.png](https://media.arcblock.io/lib/fe/feab879cf1a8f013312e94a91730ca44.w1600.webp) --- ## DID Names - DID Names Logo ![Names logo.png](https://media.arcblock.io/lib/3d/3dfed589ecb0a71a132af5c645cad2d8.w1600.webp) - DID Names Logo & Text(Light, Dark) ![DID Names-light.png](https://media.arcblock.io/lib/1d/1d9d675d3ae0784a5ab3b5a70694202f.w1600.webp) ![DID Names-dark.png](https://media.arcblock.io/lib/39/39d85dd0e73958901f2f26988c98113f.w1600.webp) --- ## DID Spaces - DID Spaces Logo ![Spaces logo.png](https://media.arcblock.io/lib/25/253611b0594dd39c8af50a8b447c8ab8.w1600.webp) - DID Spaces Logo & Text(Light, Dark) ![DID Spaces-light.png](https://media.arcblock.io/lib/4a/4a2c969ff88af1e10b7ea3870e45fcb9.w1600.webp) ![DID Spaces-dark.png](https://media.arcblock.io/lib/5e/5ee77c08f1c08fdb7444dbe930f1dd1b.w1600.webp) --- ## DID Connect - DID Connect Logo ![Connect logo.png](https://media.arcblock.io/lib/e6/e6e90789ded21a011d459b1bb2304236.w1600.webp) - DID Connect Logo & Text(Light, Dark) ![DID Connect-light.png](https://media.arcblock.io/lib/53/53fd8a4245ccabbbd913b90536ef14ab.w1600.webp) ![DID Connect-dark.png](https://media.arcblock.io/lib/8b/8b7b1f7102b329a672e68eee8378620c.w1600.webp) --- ## DID Wallet - DID Wallet Logo ![DID Wallet@4x.png](https://media.arcblock.io/lib/e2/e2d1255cb59e05870d9ae2ee986c9152.w1600.webp) - DID Wallett Logo & Text(Light, Dark) ![DID Wallet-light@4x.png](https://media.arcblock.io/lib/f3/f391ad0596c6ef7e5375abc55ee15221.w1600.webp) ![DID Wallet-dark@4x.png](https://media.arcblock.io/lib/63/639c632883139a3423fa79a175f918cb.w1600.webp) --- ### DID Logo Text Font > [!NOTE] > Brand typography [Google fonts Link ->](https://fonts.google.com/specimen/Lato?query=Lato) ### DID Logo Colors | Name | Description | Color | |---|---|---| | Brand Gradient | #079AFF | #079AFF | | Logo Text | #000000 | #000000 | | White Logo | #FFFFFF | #FFFFFF | --- ## ArcBlock Logos URL: https://www.arcblock.io/en/docs/arcblock-media-kit/media-kit/ > **Deprecated.** Current files live on [Media Assets](/en/docs/media-assets/). Keep this URL for history. ## All image resources [🗂 Download ArcBlock Logos Media Kit(SVG, PNG)](https://www.arcblock.io/image-bin/uploads/57bb3e2eb314d4ce612854b153dcbbab.zip?filename=ArcBlock-Logos.zip) ## ArcBlock Logo & Text ![Image](https://media.arcblock.io/lib/66/666b5c71fdfd2128b443c76e6179eb50.w1600.webp) ![Image](https://media.arcblock.io/lib/92/92c0fbf031e2a487d44fc4f91c143f43.w1600.webp) ![Image](https://media.arcblock.io/lib/63/639e1bbb7481eeeed33c39e875a3df7d.w1600.webp) ![Image](https://media.arcblock.io/lib/b8/b802d13a892707af83c0f57a2f994456.w1600.webp) ![Image](https://media.arcblock.io/lib/fa/fae02cbdad6d1340b3653b88f82295a6.w1600.webp) ![Image](https://media.arcblock.io/lib/82/82fabcf29b77e21663285e0368d4405f.w1600.webp)![Image](https://media.arcblock.io/lib/33/3311280269f53859df85d91bba08dcbd.w1600.webp) ![Image](https://media.arcblock.io/lib/8c/8cca6e8f2392eb40b00fec71cc1af478.w1600.webp) ## ArcBlock Logo ![Image](https://media.arcblock.io/lib/f6/f6f993de06bd5c410af6285e663312c3.w1600.webp) ![Image](https://media.arcblock.io/lib/4a/4ae9aae052bfbfb00f84d51a4d6e5a9b.w1600.webp) ![Image](https://media.arcblock.io/lib/ad/ad5acf624b032b8513c6bbfc36fe4ea3.w1600.webp) ![Image](https://media.arcblock.io/lib/23/23d90363dd498b0c1b44db8c837fa482.w1600.webp) ![Image](https://media.arcblock.io/lib/fa/fa3198c09a032156b83b6f87643eba35.w1600.webp) ![Image](https://media.arcblock.io/lib/bf/bf2278cd165503a58e9c430a4968cd2e.w1600.webp) ![Image](https://media.arcblock.io/lib/50/5074c75c4ff0649005629798fc63f0f4.w1600.webp)![Image](https://media.arcblock.io/lib/79/79be912f51680c985db9e0890257bf5b.w1600.webp) ## ArcBlock Text ![Image](https://media.arcblock.io/lib/d7/d752e6b54552ec16d1863d60bab18fa8.w1600.webp) ![Image](https://media.arcblock.io/lib/8a/8a6a26bfbcb774717a4e8fee49294b6b.w1600.webp) ## ABT Token ![Image](https://media.arcblock.io/lib/c9/c9c16d5c46f8c4edc79cf9c96a9900d7.w1600.webp) ## ArcBlock Logo Text Font > [!NOTE] > Brand typography [Google fonts Link ->](https://fonts.google.com/specimen/Lato?query=Lato) ## ArcBlock Logo Colors Pages Kit component data is missing; see the surrounding documentation. --- ## Payment Kit Guide URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/ --- ## How to Configure Additional Payment Methods URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/add-payment-mothods/ This guide explains how to configure additional payment options for EVM-compatible chains. ## 1. Add a Payment Method (EVM Chain) Navigate toayments → Settings → Payment Methods → Add Payment Method ![image.png](https://media.arcblock.io/lib/23/238e4c611b14f809d6b395628af5cc6b.w1600.webp) Then, enter the following: - Name: The name of the chain, e.g., “Ethereum” or “Base” - Description: A short description of the network (e.g., "Polygon is a scalable Ethereum Layer 2 chain") - RPC Endpoint: A valid node RPC URL, e.g., - - 👉 Where to get RPC endpoints? - - [Infura](https://www.infura.io/networks/ethereum) - [PublicNode](https://ethereum.publicnode.com) - [ChainList](https://chainlist.org) - Example: - - Ethereum: [`https://ethereum-rpc.publicnode.com`](https://ethereum-rpc.publicnode.com) - Base: [`https://base-rpc.publicnode.com`](https://base-rpc.publicnode.com) - Explorer Host: The blockchain explorer for viewing transaction history, e.g., - - Example: - - Ethereum: [`https://etherscan.io/`](https://etherscan.io/) - Base: [`https://basescan.org/`](https://basescan.org/) ![image.png](https://media.arcblock.io/lib/50/502868af2a781fd0669256f99e2b1d9f.w1600.webp) Once saved, the chain will be initialized and ready for use. --- ## 2. Add Currencies ![image.png](https://media.arcblock.io/lib/b1/b148b087b2518764dae7fe66d7af23ec.w1600.webp) To enable tokens on the newly added chain: Payments → Settings → [Your Method] → Add Currency You have two options: - Quick Add: Select a predefined currency from the list. All token info (contract, symbol, logo) will be prefilled. - Manual Entry: Enter token info manually: - - Token Name: e.g., "USDC" - Description: e.g., “Stablecoin for payments” - Contract Address: Must match the on-chain deployed token - Logo URL (optional): Used in UI; default logo is used if not set After saving, the currency will become available in checkouts and billing. --- ## 3. Deposit for Gas Fees To perform transactions on a chain, your application wallet must have the chain's native token (e.g., ETH). Steps: 1. Go to Payments → Settings → [Your Method] 2. Locate your application wallet address under the Deposit section 3. Use an external wallet to send the required gas token: 4. - ETH for Ethereum/Base 5. After the deposit, your wallet balance will appear in Overview and Settings ![image.png](https://media.arcblock.io/lib/ad/adf82a2d953de15ac159a628a7eb1cdc.w1600.webp) ### Ready to Use in Pricing After completing the above steps, you can select the new payment method and its currencies when configuring product pricing. --- ## Development Guide URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/dev-guide/ # Overview To programmatically integrate Payment Kit, you can refer to [DID Connect UI (React)](https://www.arcblock.io/docs/payment-kit-react) and [Payment Kit SDK (Node.js)](https://www.arcblock.io/docs/payment-kit-sdk). This guide will also cover solutions to common developer scenarios: - [Payment Kit Event Listening Mechanism](/en/docs/arcblock-payment-kit/events/) - [How to activate the donation feature?](/en/docs/arcblock-payment-kit/enable-donate/) - [Custom Notification Processing Guide](/en/docs/arcblock-payment-kit/manual-notification/) - [ How to Configure Additional Payment Methods](/en/docs/arcblock-payment-kit/add-payment-mothods/) --- ## How to activate the donation feature? URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/enable-donate/ @blocklet/payment-react offers a robust tipping and donation feature. Using the `CheckoutDonate` component and the optional `DonateProvider`, developers can easily integrate donation support for articles, content, and other services, seamlessly leveraging Blocklet's payment infrastructure. This guide details how to enable tipping, including installing dependencies and integrating the necessary code. ## Step 1: Install the Payment Kit Payment Kit powers the tipping feature. You need to download and install Payment Kit from the Blocklet Store: - Test Store [Payment Kit](https://test.store.blocklet.dev/blocklets/z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk) - Store [Payment Kit](https://store.blocklet.dev/blocklets/z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk) ###### Installation 1. Visit the link above to select the appropriate store for your environment (test or production). 2. Download and deploy the Payment Kit to your Blocklet application. 3. After installation, retrieve the `session` and `connectApi` configurations to connect to the Payment Kit's authentication and payment services. > Note: Use the test store for development and debugging, and the production store for production environments. Ensure your Payment Kit is running and communicating with your front-end application. ## Step 2: Install the @blocklet/payment-react package Install the component library in your React project: ```javascript npm install @blocklet/payment-react ``` ## Step 3: Integrate the tipping component You can integrate tipping functionality in two ways, depending on your needs: ### Method 1: Basic Usage — CheckoutDonate Use the `CheckoutDonate` component directly for a simple, pre-configured donation integration. ```javascript import { PaymentProvider, CheckoutDonate } from '@blocklet/payment-react'; function DonationButton() { return ( ', // Custom icon (replace with actual JSX component) size: 'large', // Button size color: 'error', // Button color variant: 'contained', // Button style }, history: { variant: 'default', // Display style for donation history }, }, }} /> ); } export default DonationButton; ``` ### Method 2: Advanced Usage — DonateProvider (Recommended) From Payment Kit version 1.18.7 onward, `DonateProvider` allows centralized management of donation settings and activation status within Payment Kit, simplifying front-end code and facilitating dynamic control over donations. ```javascript import { PaymentProvider, DonateProvider, CheckoutDonate } from '@blocklet/payment-react'; function DonationButton() { return ( ); } export default DonationButton; ``` ##### Configuration - target: A unique string identifying the reward recipient (e.g., an article or other content). - beneficiaries.address: Replace with the actual beneficiary's DID. - DonateProvider: Requires Payment Kit version 1.18.7 or later for integrated management. ##### Important Considerations - Version Compatibility: To use `DonateProvider`, you must use Payment Kit version 1.18.7 or later. Otherwise, use the basic method. --- ## Enable SubGuard™ for subscriptions? URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/enable-overdraft-protection-on-launcher/ [Payment v1.17.0: Keep Your Subscription Running with SubGuard™ & Delegation Check](/en/articles/payment-kit-v117-sub-guard/#consumer-experience) Enabling SubGuard™ for your application in Launcher ensures uninterrupted subscription services, even in cases of payment failures. This guide will walk you through the steps to activate this feature. #### Step 1: Access the Application Management Page Open [the Launcher app management page](https://launcher.arcblock.io/app/u/apps) to view all your apps. From there, you can choose which app you would like to manage. #### Step 2: Access Your Subscription Details 1. Locate the application you want to enable SubGuard™, and click the Subscription button. ![image.png](https://media.arcblock.io/lib/8a/8ac9703c3f8869e3b4be6df3a69d002b.w1600.webp) 1. Access the subscription details page to review your current subscription information. #### Step 3: Set Up SubGuard™ 1. Locate the SubGuard™ section on the subscription details page. 2. Click the button to enable SubGuard™. 3. Set the staking amount to ensure it covers the following fees: 4. - Estimated billing amount for at least one cycle. - SubGuard™ service fee. ![image.png](https://media.arcblock.io/lib/80/803a51a35b35e5a52bc4a95606c9b454.w1600.webp) Once the setup is finalized, the system will offer complete coverage for your subscription throughout the protection period, ensuring that service interruptions caused by payment failures are avoided. #### About SubGuard™ Key Features: - Continuity Assurance: Ensures your subscription services remain uninterrupted throughout the protection period. - Flexible Billing: Users can settle bills manually without incurring service fees or let the system automatically settle bills using the staked amount after the protection period (with a service fee). - Notification System: The system sends alerts if the staked amount is insufficient, helping users maintain their subscription status. Supported Currencies: - Currently supports Arcblock tokens (USD and ETH are not supported). Closing SubGuard™: - After settling bills, users can disable SubGuard™ at any time. If the subscription is canceled, any remaining stake will be refunded automatically. #### #### Benefits of SubGuard™ ::::steps :::step{title="Improving Subscription Reliability:"} Minimizing service disruptions due to payment failures. ::: :::step{title="Enhanced Flexibility:"} Users can manage their billing and payment methods to suit their preferences. ::: :::step{title="Seamless Experience:"} Ideally suited for scenarios that require uninterrupted service. ::: :::: By following these steps, you can leverage SubGuard™ to ensure a smooth and secure subscription experience for your application. For more details or assistance, visit [Arcblock Community](https://community.arcblock.io/discussions/boards/payment-kit). --- ## Payment Kit Event Listening Mechanism URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/events/ Payment Kit provides two ways to listen for events, enabling you to respond to system events in a timely manner. ## Listening Modes ### Method 1: Using Webhooks Suitable for distributed systems and supports cross-service communication. 1. Register a webhook endpoint ```javascript const ensureWebhooks = async () => { const enabledEvents = [ 'customer.subscription.started', 'customer.subscription.renewed', ]; const result = await payment.webhookEndpoints.list({ page: 1, size: 100 }); if (result.list.length) { const webhook = await payment.webhookEndpoints.update(result.list[0].id, { url: getUrl('/api/payment/callback'), enabled_events: enabledEvents, }); logger.info('webhooks updated', webhook); return; } const webhook = await payment.webhookEndpoints.create({ url: getUrl('/api/payment/callback'), enabled_events: enabledEvents, }); logger.info('webhooks created', webhook); }; ``` 1. Implement callback processing ```javascript // api/routes/payment/callback.js const { verifySig } = require('@blocklet/sdk/lib/middlewares/component'); router.post('/payment/callback', verifySig, (req, res) => { const event = req.body; switch(event.type) { case 'customer.subscription.started': await handleSubscriptionStart(event.data); break; case 'customer.subscription.renewed': await handleSubscriptionRenew(event.data); break; } } ``` ### Method 2: Using the Event Bus Suitable for handling events within a single application, simplifying implementation. ```javascript const EventBus = require('@blocklet/sdk/service/eventbus'); EventBus.subscribe((event) => { switch(event.type) { case 'customer.subscription.started': handleSubscriptionStart(event.data); break; case 'customer.subscription.renewed': handleSubscriptionRenew(event.data); break; } }); ``` ## Event Type Descriptions ### Checkout Complete - `checkout.session.completed` - Checkout session completed - `checkout.session.nft_minted` - NFT minting complete ### Subscribing to Events - `customer.subscription.created` - Customer subscription created - `customer.subscription.started` - Subscription initiated - `customer.subscription.renewed` - Customer subscription renewed - `customer.subscription.upgraded` - Customer Subscription Upgraded - `customer.subscription.updated` - Customer subscription updated - `customer.subscription.deleted` - Subscription canceled - `customer.subscription.paused` - Customer subscription paused - `customer.subscription.resumed` - Subscription resumed ### Probationary Period Incident - `customer.subscription.trial_start` - Trial Start Date - `customer.subscription.trial_will_end` - Your trial will end soon. - `customer.subscription.trial_end` - Trial End ### Payment Events - `payment_intent.succeeded` - Payment successful - `payment_intent.payment_failed` - Payment failed - `invoice.paid` - Invoice payment completed - `refund.succeeded` - Refund successful --- ## Custom Notification Processing Guide URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/manual-notification/ Payment Kit allows applications to handle notifications directly, offering two configuration options. ## Option 1: Subscription-Based Access Control When creating a `checkoutSession`, use `subscription_data.notification_settings` to configure notification handling. ```javascript const checkoutSession = await payment.checkout.sessions.create({ mode: 'subscription', line_items: [{ price_id: 'your_price_id', quantity: 1 }], subscription_data: { notification_settings: { self_handle: true, // enable custom processing include_events: ['customer.subscription.started'] } } }); ``` ## Approach 2: Global Management Create global notification configurations using the `settings` API. ```javascript // 1. create global setting const setting = await payment.settings.create({ type: 'notification', mountLocation: 'your.app.id', // use component_did or custom global constant description: 'manual notification', componentDid: '', // optional, component did settings: { self_handle: true, // enable custom processing include_events: [ 'customer.subscription.started', 'customer.subscription.renewed' ] } }); // 2. releated settings to checkout session const checkoutSession = await payment.checkout.sessions.create({ mode: 'subscription', line_items: [{ price_id: 'your_price_id', quantity: 1 }], metadata: { setting_id: setting.id // setting id or mountLocation value } }); ``` ## Listening for Events [Payment Kit 事件监听机制](/en/docs/arcblock-payment-kit/events/) ### Method 1: Using a Webhook 1. Register a webhook endpoint ```javascript const enabledEvents = [ 'customer.subscription.started', 'customer.subscription.renewed', 'manual.notification', ]; const webhook = await payment.webhookEndpoints.create({ url: 'https://your-app.com/api/payment/callback', enabled_events: enabledEvents }); ``` 1. Implement webhook processing ```javascript // api/routes/payment/callback.js module.exports = { post: async (req) => { const event = req.body; if (event.type === 'manual.notification') { await sendCustomEmail(event.data); } return { code: 'OK' }; } }; ``` ### Using the Event Bus Use the `@blocklet/sdk` EventBus to listen for events within the application: ```javascript const EventBus = require('@blocklet/sdk/service/eventbus'); EventBus.subscribe((event) => { if (event.type === 'manual.notification') { sendCustomEmail(event.data.object); } }); ``` ### Notification Data Structure ```javascript { type: 'customer.subscription.started', // original trigger event type data: { entity: any, // Notify related entity data (subscription, billing information, etc.) userDid: string, context: { // Payment Kit Context information for notifications that have been processed [key: string]: any } } } ``` ## Best Practices 1. Selecting the Appropriate Configuration Level 2. - Subscription level: For scenarios where different subscriptions require different notification policies - Global level: Applies to all subscriptions that use a unified notification policy. 3. Listener Mode 4. - Webhook: Ideal for distributed systems, facilitating inter-service communication - EventBus: Ideal for managing events within a single application, offering a simpler implementation. --- ## Welcome to Payment Kit. URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/payment-intro/ Payment Kit is ArcBlock's powerful payment solution designed to help developers quickly and easily integrate diverse payment functionalities into their applications. From creating products and generating payment links to building sophisticated payment experiences, Payment Kit offers flexible and efficient support. Here is an overview of its core features: - Create Products: Payment Kit makes it easy to create and manage products and services, allowing you to define product details and build a solid foundation for your business. - Payment Links: Create and share payment links in just a few steps to streamline transactions and improve the customer experience. - Pricing Table: Create visually appealing and easy-to-understand pricing tables for your products to present pricing information, attract potential customers, and drive sales. Pro Features 🔥 - Tip Feature: The `` component allows developers to easily integrate a tipping button into their applications, enabling users to quickly and conveniently support creators and service providers. [Get started now.](/en/docs/arcblock-payment-kit/enable-donate/) - Payment Methods: Supports multiple payment methods and currencies to meet the needs of a global audience. - API Integration: A dedicated JavaScript SDK facilitates the implementation of highly customized payment solutions for complex business requirements. Payment Kit offers two robust SDKs: - @blocklet/payment-js: A Node.js SDK for implementing backend payment logic. [Learn more -> ](/en/docs/arcblock-payment-kit/payment-js/) - @blocklet/payment-react: A React component library offering ready-to-use payment UI components.[Learn More ->](/en/docs/arcblock-payment-kit/payment-react/) --- ## Acquire the Payment Kit [Payment Kit](https://store.blocklet.dev/blocklets/z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk) ## Getting Started and Using - [安全](/en/docs/arcblock-payment-kit/security-g6CVr/) - [安全](/en/docs/arcblock-payment-kit/security-g6CVr/) --- ## Stay Updated For more information on Payment Kit releases and updates, see our official blog posts: [ArcBlock Official Site](/en/articles/) --- ## Security URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/security-g6CVr/ - [How to configure and enable the Vault Wallet ](/en/docs/arcblock-payment-kit/vault-config/) --- ## User Guides URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/user-guide/ - [Enable SubGuard™ for subscriptions?](/en/docs/arcblock-payment-kit/enable-overdraft-protection-on-launcher/) --- ## How to configure and enable the Vault Wallet URL: https://www.arcblock.io/en/docs/arcblock-payment-kit/vault-config/ ## 1. Key Features of the Vault Wallet ### The Current State of Hot Wallets Currently, all app revenue is stored by default in a hot wallet. While this facilitates real-time transactions, it also presents security risks. - Constant internet connectivity increases vulnerability to network attacks - All funds are concentrated in a single hot wallet ### The Value of Vault Wallet Vault Wallet protects assets through physical isolation: - Automatic Sweep: Automatically transfers funds when the hot wallet balance exceeds a predefined threshold. - Funds Security: The majority of funds are held in offline storage. ## 2. Configure a Vault Wallet for the Application ### Prerequisites - App Owner Privileges - A valid wallet address (compatible with both ArcBlock native and ETH addresses) ### Procedure ![image.png](https://media.arcblock.io/lib/69/690ef53bb26f78d30d355b67e9daa033.w1600.webp) ::::steps :::step{title="Go to the Blocklet Service Dashboard"} ::: :::: ::::steps :::step{title="Select Operations → Advanced"} ::: :::: ::::steps :::step{title="Setup Vault"} ::: :::: > Your vault wallet address can be the same as your owner wallet address. Note that if you change your vault wallet address, the previous address will be considered insecure and can no longer be used as the vault wallet for this application. ## Enable Vault Wallet Support for Payment Currencies in Payment Kit ### Functionality ```javascript Hot wallet balance monitoring → exceeds threshold → triggers automatic transfer → funds enter vault wallet ``` ### Setup ::::steps :::step{title="Configure Vault"} ::: :::: - Navigation: `Payment > Settings > Vault` ::::steps :::step{title="Configure Currency Rules"} ::: :::: - Select the currency (e.g., ETH/ABT) - Input Deposit Threshold, Buffer Threshold - Click Save ![image.png](https://media.arcblock.io/lib/0e/0e6e255a5e6e808ae1294ef88661956e.w1600.webp) --- ## AI Application Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/ai-application-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job responsibilities 💡 Depending on individual abilities and interests, you can choose to participate in any number of the following jobs. - Participate in the development and maintenance of AI Kit, AI Studio, and AI applications. - Design and implement user-oriented product features, deliver high-quality, user-friendly WEB applications, and even cross-platform applications. - Participate in the end-to-end architecture and support of various decentralized applications. - Optimize the code coverage, delivery pipeline, and level of automation for the project responsible. ## Ability Requirements - Familiar with AI API, with practical usage experience. - Solid JavaScript, HTML, and CSS3 foundation, proficient in responsive layout, familiar with ES6, HTTP protocol. - Familiar with any front-end framework, such as React.js, Vue.js, it is better to be familiar with React.js. - Familiar with any backend framework, such as Express.js, Koa, etc. - Familiar with computer networks, understand distributed systems, common security issues and prevention measures. - Familiar with GraphQL, capable of designing and implementing well-functioning backend APIs. - Ability to design architecture, implement engineering, and operate online maintenance according to system requirements. - Used Jest, GitHub Actions, commonly seen libraries for logging and database interaction. - Understanding common architectures and optimization methods for back-end systems, such as caching, load balancing. - Strong self-learning ability and an open mindset, continuously learning new technologies and tools to improve the efficiency of the whole team. - With good engineering literacy, such as code style, Git workflow, able to write high-quality front-end code. - Familiar with Linux and Unix operating systems, familiar with Nginx, able to complete common operations and maintenance tasks. - Familiar with Amazon AWS or other cloud computing platforms (such as Azure, Google Cloud, Digital Ocean, Alibaba Cloud, etc.) ## Bonus item - Have a strong interest in AI, have used AI products extensively, and have their own insights. - Own AI work. - Experience in developing with Typescript - Experience building front-end applications using React.js, experience with Docker. - Familiar with basic blockchain conceptual models, linking common public chain operation mechanisms, better if you have developed applications on other public chains. - Leadership capabilities, product capabilities, and best engineering practices demonstrated in past experiences. - Good communication skills: Effective communication with peers and non-technical personnel, such as document writing. - High-quality GitHub open source projects, technical blogs. - Have experience using [Electron](https://www.electronjs.org/) and project experience, familiar with Service Worker. --- ## Android Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/android-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job responsibilities - Design and implement user-oriented product features, deliver high-quality software, including but not limited to: DID Wallet Android version, DID Wallet Android SDK. - Optimize the delivery pipeline and level of automation for each project. - Provide technical support for our customers and partners. ## Ability requirements - Having more than 2 years of practical development experience in Android, familiar with Android SDK and related technologies for development, debugging, optimization, release, and integration. - Proficient in mastering the Kotlin language. - Familiar with Android threads, processes, Bundles, and Handler mechanisms. - Familiar with Android custom drawing and animation implementation; - Proficient in using OkHttp, Retrofit, RxJava, Glide, Gson and other common third-party libraries. - Proficient in using git. - Understand or be familiar with Javascript/Node.js projects. - Based on product requirements design solutions, ability to drive product landing. - Strong self-learning ability and a relatively open mindset, constantly learning new technologies and tools to improve the efficiency of the entire team. ## Bonus points - Familiar with basic concepts and algorithms of blockchain. - Have experience developing with other backend languages. - Experience in developing Native Apps for iOS. - High-quality GitHub open source projects, technical blogs. - Familiar with any modern front-end framework, such as React, Vue.js, Angular. - Leadership capabilities, product capabilities, and best engineering practices demonstrated in past experiences. - Good communication skills: effectively communicate with peers, non-technical personnel, such as document writing. - Familiar with Amazon AWS or other cloud computing tools and technologies such as Azure, Google Cloud, Alibaba Cloud, etc. --- ## Full-Stack JS Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/full-stack-js-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job Responsibilities 💡 You can choose to participate in any of the following jobs based on your ability and interest - Design and implement user-facing product features to deliver high quality, smooth user experience web applications, even cross-platform applications - Participate in the design, implementation, and delivery of [Blocklet Server](https://www.npmjs.com/package/@blocklet/cli) kernel functionality and console functionality, ensuring high performance and security - Participate in the design, implementation, delivery and stable operation and maintenance of [Blocklet Launcher](https://launcher.arcblock.io/home/) functionality, and extend it to more cloud platforms - Participate in the iteration of [Blocklet SDK](https://www.npmjs.com/package/@blocklet/sdk), design and improvement of Blocklet Service, and provide efficient application development framework. - Participate in the development iterations of the [blockchain](https://main.abtnetwork.io/explorer) and its [SDK](https://www.npmjs.com/package/@ocap/client) to help improve the performance, security and scalability of each layer of the chain - Participate in the end-to-end architecture and support of various decentralized applications, such as our Rollup solution - Optimize code coverage, delivery pipeline, and automation levels for projects under your responsibility ## Competency Requirements - Solid JavaScript, HTML, CSS3 skills, familiar with responsive layout, familiar with ES6, HTTP protocol - Familiarity with any front-end framework, such as React.js, Vue.js, familiarity with React.js is a plus - Familiarity with any back-end frameworks, such as Express.js, Koa, etc. - Familiar with computer networks, understanding of distributed systems, common security issues and means to prevent them - Familiar with GraphQL, able to design and implement a good back-end API - Ability to design, engineer and implement architecture based on system requirements and go live for operations and maintenance - Have used Jest, GitHub Actions, common logging, DB interaction libraries - Understanding of common back-end system architecture and optimization methods, such as caching, load balancing - Strong self-learning ability and open-mindedness, constantly learning new technologies and tools to improve the efficiency of the whole team - Good engineering skills, such as code style, Git workflow, and ability to write high quality front-end code - Familiar with Linux, Unix operating systems, Nginx, and the ability to perform common operations and maintenance tasks - Familiar with Amazon AWS or other cloud computing platforms (e.g. Azure, Google Cloud, Digital Ocean, Ali Cloud, etc.) ## Bonus points - Experience building front-end applications using React.js and experience using Docker - Familiarity with basic blockchain conceptual models, links to common public chain operating mechanisms, and application development on other public chains is a plus - Demonstrated leadership, product capability, and engineering best practices from past experience - Good presentation skills: effective communication with peers, non-technical staff, and then documentation for example - High quality GitHub open source projects, technical blogs - Experience with Electron and projects, familiarity with Service Worker --- ## arcblock/hr-assistant URL: https://www.arcblock.io/en/docs/arcblock/hr-assistant/ --- ## iOS Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/ios-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job Responsibilities - Design and implement user-oriented product features, deliver high-quality software, including but not limited to: DID Wallet iOS version, DID Wallet iOS SDK. - Optimize the delivery pipelines and automation levels of each project. - Provide technical support for our customers and partners. ## Ability requirement - Have 2 years or more experience in Internet or blockchain industry, good engineering literacy, such as coding style, Git workflow. - Has rich experience in mobile application development, strict requirements for the quality of mobile products, and pursues perfection in details. - Possess a solid foundation in Swift (required), Object-C language, and understanding language features. - Can achieve more complex interfaces and visual effects, handle the logical relationship with data well, and ensure stability. - Familiar with the packaging and publishing process, with experience in AppStore application deployment. - According to product requirements, design solutions, and promote the ability to land products. - Strong self-learning ability and a relatively open mindset, continuously learning new technologies and tools to improve the efficiency of the entire team. ## Bonus points - Familiar with basic concepts and algorithms of blockchain. - Have experience in developing with other backend languages - Experience in developing native apps for Android - High-quality GitHub open source projects, technical blogs. - Familiar with any modern front-end frameworks, such as React, Vue.js, Angular. - Leadership ability, product ability, engineering best practices capability displayed in past experiences. - Good communication skills: effectively communicate with colleagues and non-technical staff, such as document writing. - Familiar with Amazon AWS or other cloud computing tools and technologies such as Azure, Google Cloud, Alibaba Cloud, etc. --- ## Join Us URL: https://www.arcblock.io/en/docs/arcblock/join-us/ ## Why join ArcBlock? ArcBlock aims to reconstruct and optimize the way blockchain applications connect with ordinary users and developers, by combining blockchain technology, cloud computing, and token economy, providing developers with diverse tools and services to facilitate more efficient and convenient development and deployment of decentralized applications. We are gradually building a complete platform and forming a rich application ecosystem. Most of our products will be open source, and some products have already been open sourced. Currently, the products we have released include: - [Blocklet Server](https://www.npmjs.com/package/@blocklet/cli): [Operating system for decentralized applications](https://developer.blocklet.io/), also a basic developer tool, can connect to any [App Store](https://store.blocklet.dev/) that follows the same protocol to find, purchase, install, and manage [Decentralized applications.](https://www.blocklet.io/). - [DID wallet](https://www.didwallet.io/): Convenient for users to manage their digital assets and digital identities, fully compatible with Ethereum, decentralized WEB3, DID wallet. - [Blockchain Framework.](https://chain.abtnet.io/): A feature-rich, layered and scalable blockchain framework that enables developers to quickly launch their own application chains, supporting cross-chain transactions and contract mechanisms. The products we release need to meet high quality, high performance, high reliability, and scalability requirements, and support large-scale, 24/7 operation. We need your help to make this happen. If you can adapt to remote work, manage your own time, appreciate transparency in company culture, collaborate with an international team distributed globally, pursue engineering quality, focus on development efficiency, love to learn and research the latest technology, then our Full Stack Engineer position will be very suitable for you! Full-stack engineers are important forces driving the growth of [ArcBlock](https://www.arcblock.io/) platform, participating in weekly team planning meetings, all-staff briefings, and responsible for core products such as wallets, nodes, and blockchain frameworks for users. Submitting a resume? Please send an email to [hr@arcblock.io](mailto:hr@arcblock.io) ## Referral Reward Program For each of our positions, once officially hired (after passing the probation period), the referrer will be rewarded with 1,000 ABT or an equivalent amount in cash (the method of reward will be determined by the company according to local legal requirements, etc.). - If it is a self-recommendation, the reward will be granted to the hired employee. - For referrers, the recommended relationship must be confirmed by the hired employee. - The referral reward program does not apply to HR service agencies or individuals contracted with the company, or to internal employees who have a direct leadership with the position. ArcBlock reserves the right to modify and interpret the details of the referral reward program at any time. ## How do we work? - We use GitHub to host all of our code, task management and tracking are also based on GitHub. - We use GitHub Actions to run tests, build, package, and release products. - We use [Blocklet Server](https://www.npmjs.com/package/@blocklet/cli) to deploy all websites, applications, chains. Blocklet Server is our own product. - We use JavaScript to develop most applications and SDKs, heavily utilizing React.js, MUI, and Node.js. - We use Markdown to write various documents, blogs, and pages, and use Notion to manage internal knowledge. - We advocate for results-oriented approach, and will ensure the elegance of the solution through code review. - We advocate automation, reducing the initial cost and delivery time of projects as much as possible. - We try our best not to reinvent the wheel. The vast majority of modules and services are designed with reusability in mind from the beginning. ## What can we offer? - Choose work equipment according to your needs. The basic configuration is a MacBook Pro + a large high-definition display screen. - All remote methods, free and flexible time, colleagues distributed in different places. - Competitive salary, token incentive plan, diversified and flexible salary schemes. - A working atmosphere full of trust, end-to-end empowerment. As long as you have the willingness and ability, you can fully hold the product, technology design, and research and development on your own. - Rapid growth, technology-first, focus on delivery, user-centric, goal-oriented team. - To assist employees in their growth, expenses related to work-related skills training courses and technical conferences can be reimbursed directly. - At least 10 days of paid annual leave each year, plus flexible paid sick leave. ## What positions are currently open? - [What is our recruitment process?](/en/docs/arcblock/recruitment-process/) - [WEB Front-end Engineer (Filled)](/en/docs/arcblock/web-front-end-engineer-career/) - [Android Engineer (Filled)](/en/docs/arcblock/android-engineer-career/) - [AI Application Engineer (Filled)](/en/docs/arcblock/ai-application-engineer-career/) - [iOS Engineer (Filled)](/en/docs/arcblock/ios-engineer-career/) - [Full-Stack JS Engineer (Filled)](/en/docs/arcblock/full-stack-js-engineer-career/) - [JS backend engineer (Filled)](/en/docs/arcblock/js-backend-engineer-career/) - [UI/UX designer (Filled)](/en/docs/arcblock/ui-ux-designer/) - [Site Reliability Engineer (Filled)](/en/docs/arcblock/sre-jd/) - [HR 助理(已招满)](/en/docs/arcblock/hr-assistant/) --- ## JS backend engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/js-backend-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job Responsibilities - Design and implement user-oriented product features, deliver high-quality, high-performance, secure backend services. - Participate in discussions, design, implementation, and delivery of [Blocklet Server](https://www.npmjs.com/package/@blocklet/cli) kernel functions, providing stable, high-performance application runtimes. - Participate in the design, implementation, delivery, and stable operation of [Blocklet Launcher](https://launcher.arcblock.io/) functionality, and extend it to more cloud platforms. - Participate in the iteration of [Blocklet SDK](https://www.npmjs.com/package/@blocklet/sdk), design and improve the Blocklet Service, providing an efficient application development framework. - Participate in the development iteration of [Asset chain](https://main.abtnetwork.io/) and [SDK](https://www.npmjs.com/package/@ocap/client), assist in improving the performance, security, and scalability of each layer of the chain. - Participate in the backend architecture and support of various decentralized applications, such as our Rollup solution. - Optimize the code coverage, delivery pipeline, and automation level of the responsible project. ## Ability requirements - Familiar with the JavaScript language, proficient in using frameworks such as Express.js, Koa, etc. - Familiar with computer networks, understand distributed systems, common security issues, and prevention measures. - Familiar with GraphQL, able to design and implement well-structured backend APIs. - The ability to design architecture, implement engineering, and operate online according to system requirements. - Using Jest, GitHub Actions, common logging, and database interaction libraries. - Understanding common architectures and optimization methods for backend systems, such as caching, load balancing. - Strong self-learning ability and an open mindset, continuously learning new technologies and tools to improve the efficiency of the entire team. - Having good engineering literacy, such as coding style, Git workflow, able to write high-quality front-end code. - Familiar with Linux and Unix operating systems, familiar with Nginx, able to complete common operation and maintenance tasks. - Familiar with Amazon AWS or other cloud computing platforms (such as Azure, Google Cloud, Digital Ocean, Alibaba Cloud, etc.) ## Extra credit points - Experience in building front-end applications using React.js, experience with Docker. - Familiar with basic blockchain concepts and models, understand common public chain operation mechanisms, better if you have experience in application development on other public chains. - Leadership abilities, product capabilities, and best engineering practices demonstrated in past experiences. - Good communication skills: effective communication with peers, non-technical personnel, and document writing. - High quality GitHub open source projects, technical blogs. --- ## What is our recruitment process? URL: https://www.arcblock.io/en/docs/arcblock/recruitment-process/ What are the steps to successfully join ArcBlock? How should one prepare? You can take a look at two articles written by CEO. [How to easily pass through ArcBlock's recruitment process](/en/articles/how-to-get-through-arcblock-interview-process/) [How to successfully pass the interview of ArcBlock's UI/UX designer](/en/articles/2021-01-22-how-to-get-through-ux-interview-process/) --- ## Site Reliability Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/sre-jd/ Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ### Job Responsibilities - Organize and implement comprehensive and automated online service data collection, monitoring, and alarm processes - Responsible for the daily operation and maintenance of Blocklet Server in online servers, such as upgrades and diagnostics - Responsible for automated, standardized online service data, team code, and knowledge base backups - Responsible for daily security protection of online services, such as SQL injection, denial of service tools, etc. - Responsible for providing basic data, error, and log collection services for online services, such as Sentry - Assist in building team data dashboards, such as team leaderboards, requiring basic application development capabilities ### Skills Required - Familiar with Node.js language for quick understanding of basic usage of Blocklet Server - Familiar with Linux, Unix operating systems, Nginx, Shell, and able to complete common operations tasks - Familiar with computer networks, with the ability to troubleshoot problems throughout the entire process - Familiar with common security issues and prevention methods, able to use cloud services or self-developed solutions - Familiar with the operation and use of common monitoring solutions, such as Sentry, InfluxDB - Familiar with common databases such as SQLite for backup, recovery, and performance optimization - Familiar with basic usage of cloud computing platforms such as Amazon AWS, Google Cloud - Good engineering literacy, such as code style, Git workflow, able to write high-quality script code - Strong self-learning ability and open mindset, continuously learning new technologies and tools to improve the efficiency of the entire team - Sense of ownership, safeguarding the performance, security, and reliability of online services ### Bonus Points - Demonstrated leadership, product, and engineering best practices in past experiences - Good communication skills: effective communication with peers, non-technical personnel, and document writing - High-quality GitHub open source projects, technical blogs --- ## UI/UX designer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/ui-ux-designer/ ## Main responsibilities - Work closely with multiple developers to advance the implementation of the project together. - Participate in the construction of ArcBlock [UX Library](https://arcblock.github.io/ux), building a well-crafted business layer component library. - Suggest improvements to existing products and propose feasible design solutions ## Ability requirements - Passionate about your role and proactive in staying informed about cutting-edge developments in product design through various channels - Proficient in Figma, familiar with its component design and variable-related functions. - Solid visual design skills, attention to detail, strong control over color and layout. - Excellent communication skills and team spirit, effective collaboration with different team members. - We do not encourage the use of high-precision redline design approach, but we hope you can provide the team with a design style and specification guidance at a higher dimensionality. ## Bonus points - Having a personal website that is maintained long-term or showcasing works on platforms like Dribbble. - Understand design implementation, such as HTML and CSS. --- ## WEB Front-end Engineer (Filled) URL: https://www.arcblock.io/en/docs/arcblock/web-front-end-engineer-career/ > Please send your resume to apply for this position: [hr@arcblock.io](mailto:hr@arcblock.io) ## Job Responsibilities - Design and implement user-facing product features to deliver high quality, smooth user experience WEB applications, even cross-end applications - Participate in the discussion, design, implementation and delivery of [Blocklet Server](https://www.npmjs.com/package/@blocklet/cli) console features, providing a complete decentralized application development workbench - Participate in the iteration of the WEB version of [DID wallet](https://web.abtwallet.io/) to provide a secure, efficient and easy-to-use WEB wallet service, similar to Metamask - Participate in the development of various decentralized applications, such as [Blocklet Store](https://store.blocklet.dev/), [Block Browser](https://main.abtnetwork.io/explorer) and other existing modules and new projects - Participate in the construction of ArcBlock [UX Library](https://arcblock.github.io/ux/?path=/story/documentation-introduction--page) to build a business layer component library with excellent experience - Optimize the code coverage, delivery pipeline, and automation level of the projects you are responsible for ## Competency requirements - Solid JavaScript, HTML, CSS3 skills, familiar with responsive layout, familiar with ES6, HTTP protocol - Familiarity with any front-end framework, such as React.js, Vue.js, preferably React.js - Familiarity with any front-end component library, such as Material UI, Ant Design, familiarity with Material UI is a plus - Have used automated testing tools such as Jest, Cypress, and GitHub Actions - Familiarity with front-end build tools, such as Webpack, Rollup, Vite, etc. - Good engineering skills, such as code style, Git workflow, and ability to write high quality front-end code - Combine front-end solutions based on product design and push the product to launch - Strong self-learning ability and open mind, constantly learning new technologies and tools to improve the efficiency of the whole team ## Extra points - Experience with [Electron](https://www.electronjs.org/) and projects, familiar with Service Worker - Experience using [Node.js](https://nodejs.org/en/), [Express](http://expressjs.com/index.html) backend, hands-on experience with SSR, SSG, familiar with GraphQL - Familiarity with Amazon AWS or other cloud computing (e.g. Azure, Google Cloud, Aliyun, etc.) tools and technologies - Familiarity with basic blockchain conceptual models, preferably having done application development on other public chains - Demonstrated leadership, product capability, and engineering best practices from previous experience - Good presentation skills: effective communication with peers, non-technical staff, and then documentation for example - High quality GitHub open source projects, technical blogs - Familiarity with Linux, Unix systems and common command line tools --- ## ArcBridge Node URL: https://www.arcblock.io/en/docs/arcbridge/ --- ## How to add stake for your node? URL: https://www.arcblock.io/en/docs/arcbridge/add-stake-for-arcbridge-node/ 1. Login to your ArcBridge Node, and open "Stake" page 2. Click "Add Stake" on the Stake page ![image.png](https://media.arcblock.io/lib/fa/fa779c179cc01a204c9b4162516fe28b.w1600.webp) 1. Input stake amount in the stake dialog: ![image.png](https://media.arcblock.io/lib/db/dbb64553a64830086424456b40b3ab3e.w1600.webp) 1. Complete the stake with your DID Wallet or send the QRCode to others ![image.png](https://media.arcblock.io/lib/04/04e1d4624d3e895ba1bf5723c6ecceb5.w1600.webp) --- ## Join ArcBridge URL: https://www.arcblock.io/en/docs/arcbridge/EEvpZgb-AsljVGGoqBvVWtWv/ You can join ArcBridge by just run the following blocklet: [ArcBridge Node](https://store.blocklet.dev/blocklets/z8iZqeUACK955YaBWqEd8aKg3tTki1GpvE2Wu) Detailed video and blog tutorial by z1TTxpjeYVMyNVwRbBjrhxa4E94UaDd6ZX9 can be found here: ::embed{url="https://x.com/i/status/1766226689896358229"} --- ## ARC Architecture URL: https://www.arcblock.io/en/docs/architecture/ --- ## AFS UI URL: https://www.arcblock.io/en/docs/architecture/afs-ui/ **AFS UI** is the architecture name for projecting AFS resources and capabilities into something a human or agent can interact with. It answers: given paths, providers, and operations, which UI device and contract present them? It is **not** a third large authoring board next to AUP and Web Device. Author interactive apps in [AUP](/en/docs/aup/). Author static sites in [Web Device](/en/docs/web-device/). Use this page only to keep those targets aligned with AFS. ## What exists in current code Checked against ARC source `44fbd616f` and packages at `2.0.0-beta.31` in tree: | Piece | Package / location | Role today | | --- | --- | --- | | AUP types and pure helpers | `@aigne/afs-aup` (`packages/aup`) | Semantic node graph, validation helpers, degradation helpers shared by devices | | Interactive UI device runtime | `@aigne/afs-ui` (`providers/runtime/ui`) | Sessions, AUP app loading, node store, event/exec wiring, web-page surfaces | | Web Device provider | `@aigne/afs-web-device` (`providers/runtime/web-device`) | Reads site trees (pages, content, `.web/`) and renders static HTML; can render supported AUP shells for sites | | AFS provider base | `@aigne/afs` (`packages/core`) | Mounts, list/read/write/search/exec, capability and access modes | AUP node fields that connect UI to AFS include `src` (read-only binding), `bind` (read-write binding), `propBind` (server-resolved prop paths), and events that map to AFS `exec`. Those fields are part of the AUP contract, not a separate “AFS UI API.” ## Architecture relationship ```text AFS (paths + providers + operations) └─ AFS UI (projection lens) ├─ AUP + UI runtime → interactive sessions / device renderers └─ Web Device → static HTML sites and content objects ``` | Concern | Owned by | Notes | | --- | --- | --- | | Path operations and provider capability | AFS | UI cannot invent an operation the provider does not declare | | Semantic tree, events, degradation | AUP | Device must report capabilities; support is not universal | | Session handshake and interactive render | UI runtime (`@aigne/afs-ui`) | Present-tense behaviour is version- and target-specific | | Site directories, markdown content, themes | Web Device | Separate from interactive session protocol | | Comments / collections surfaces on sites | Web Device + UI surface code | Platform surfaces exist; not a guarantee that every site enables them | ## What draft architecture docs claim that this page does not Internal draft materials (for example `docs/architecture/afs-ui.md` in the ARC repo) describe a broader vision: every UI element as an AFS path, a full `/dev/ui` device model, window managers, and multi-backend renderers. Treat those as **archaeology and design intent**. This public page only states: 1. AFS UI is a useful **lens** for relating UI to AFS. 2. **AUP** and **Web Device** are the documented authoring and runtime contracts. 3. There is **no** public, versioned “implement any third-party AFS UI device” extension guide with a guaranteed E2E sample for external authors—unless and until a sibling board documents one against current code. Do not infer: - Every AFS path has a UI - Every UI can write through AFS - Every renderer supports the same primitives - Old ArcBlock admin UIs are shipped as stable ARC products ## Where to go next | Task | Board | | --- | --- | | Author or validate AUP source | [AUP](/en/docs/aup/) | | Device capabilities and degradation | [AUP device capabilities](/en/docs/aup/device-capabilities-degradation/) (and related AUP pages) | | Build a static site | [Web Device](/en/docs/web-device/) | | Mount data or implement a provider | [AFS](/en/docs/afs/) | | Package the app | [Blocklets](/en/docs/blocklets/) | | Caller and session data views | [Identity & Data Spaces](/en/docs/identity-data-spaces/) | --- ## ARC and AFS URL: https://www.arcblock.io/en/docs/architecture/arc-and-afs/ Name the layers by what you depend on: | Name | Role | You reach it when… | | --- | --- | --- | | **AFS** | Path-based resource and capability abstraction | You list, read, write, search, exec, or mount a path | | **ARC** | Runtime product shell around AFS | You start a service, run a Blocklet, open a session, or use the CLI against a live instance | AFS does not know how HTTP arrived or which process hosts it. ARC does: it boots the host, mounts providers, applies identity and session context, and exposes operational tools. ## What AFS owns AFS is implemented as the `@aigne/afs` core and provider base classes. A provider declares a name, access mode, and the operations it implements. Core operations you will see in the CLI and provider contract include: | Operation family | Purpose | | --- | --- | | `list` / `read` / `write` / `delete` | Directory and entry access | | `stat` | Metadata without full content | | `search` | Provider-defined content search inside a path | | `exec` | Actions exposed as executable paths | | `explain` | Human- and agent-oriented description of a path or concept | | `mount` | Attach a provider at a path | A path is an interface boundary. It is not evidence that all data lives in one store. Check the provider’s declared capabilities before treating an operation as part of your application contract. Full operation semantics: [AFS core contract](/en/docs/afs/core-contract/). ## What ARC owns ARC is the host that makes AFS useful as a product: - Loads and mounts providers (for example Web Device, DID Space, UI device modules) - Runs Blocklet packages and instances - Builds session and caller views used by interactive and site surfaces - Exposes `arc` CLI groups (`afs`, `blocklet`, `service`, `dsl`, `space`, `did`, and others) Installed CLI surface checked for this board: `arc` `2.0.0-beta.28`. Command reference: [ARC CLI](/en/docs/arc-cli/). ## Start with the right name | Task | Start with | Why | | --- | --- | --- | | Implement or debug a path operation | AFS | The provider and operation contract decide behaviour | | Author a provider package | AFS | Mount and capability rules live there | | Run or package an application | Blocklet on ARC | Lifecycle is package/instance, not a raw path | | Render a static site | Web Device (AFS provider) via ARC | Site layout is a Web Device concern hosted by ARC | | Drive an interactive AUP app | AUP session under ARC UI runtime | Session and device handshake are runtime concerns | | Inspect who is calling | Identity board | Caller and DID Space are not AFS operation names | ## What this page does not claim - It does not publish a stable third-party “plug in any UI device” extension API. - It does not equate every historical Blocklet Server or DID product name with a current ARC module. - It does not expand experimental remote deploy or instance-DID lifecycle paths into present-tense contracts; those belong on the boards that can re-verify them. Next: [Product layers](../product-layers/) for ownership, or [AFS](/en/docs/afs/) for operations. --- ## Contracts and evidence URL: https://www.arcblock.io/en/docs/architecture/contracts-and-evidence/ Every present-tense product sentence needs a status. Without one, readers treat vision, history, and shipping behaviour as the same contract. ## Status vocabulary | Status | Meaning | Allowed on public pages | Required evidence | | --- | --- | --- | --- | | **Current contract** | Behaviour you may design against for a named target runtime | Yes, as “supports / does / rejects” | Current source or types **and** tests or observed local run on the target version | | **Architecture** | How layers fit; orientation only | Yes, clearly as explanation | Consistent with current structure; must not invent new public APIs | | **Experimental / gap** | Incomplete, partial, or not E2E-verified | Yes, only if labelled as such | State what is missing or unproven; do not soften into a promise | | **Lineage** | Why an older name still appears | Yes, with explicit non-promises | Product records, reference apps, or dependency facts—not feature parity | | **Unresolved** | Needs a product or engineering decision | Prefer issue / review notes; short public caution only | Name the decision; do not invent a default | ## Evidence order (mandatory) 1. **Current code, types, tests, and a local run** prove “now supports.” 2. **Merged PRs** prove a change landed once. Re-check the current tree; later commits may have removed or narrowed it. 3. **Planning docs, open issues, draft architecture notes, articles** are archaeology. They may guide research; they do not establish a public contract alone. 4. When sources conflict, **public docs state the current implementation**, and the conflict goes to `research-ledger.md` or an issue comment—not into a marketing rewrite. ## How to classify a sentence | Draft sentence | Correct status | Rewrite pattern | | --- | --- | --- | | “`arc afs ls` lists a path” | Current contract | Keep only after running it on the documented CLI version | | “AFS UI relates UI work to AFS paths” | Architecture | Keep as explanation; do not add “stable extension API” | | “Instance DID lifecycle is complete for all remotes” | Experimental / gap (if unproven) | Say what is verified locally; mark remote lifecycle separately | | “Discuss Kit was absorbed into ARC” | Lineage | State reference Blocklet / surfaces; deny full old-feature equivalence | | “Third parties can ship any UI device” | Unresolved / not current | Do not publish as contract until code + E2E sample exist | ## What each board type should carry | Board type | Primary status mix | | --- | --- | | Architecture (this board) | Architecture + lineage; pointers to contracts | | AFS / AUP / Web Device / Blocklets / Identity / CLI | Mostly current contract; mark experimental gaps explicitly | | Product marketing pages | May use lineage language; never invent developer contracts | ## Version pinning When a page includes commands or field-level behaviour: 1. Name the **CLI or package version** used for verification. 2. Show **actual** outputs or error shapes when the page teaches a command. 3. If your install differs, re-run before treating the page as authority. This board’s orientation facts were checked with `arc` `2.0.0-beta.28` and ARC source `44fbd616f`. Sibling boards may pin their own versions; prefer the stricter or more recent check for operational work. ## Red lines that override status Reader-visible text still follows site positioning constraints (product and technical claims only; no price or return promises; no banned marketing phrases; no claiming unimplemented features as shipped). Architecture status does not excuse a §1C overclaim. ## Related pages - Map and reading order: [Overview](../overview/) - Old product names: [Product lineage](../product-lineage/) - Term index: [Reference](../reference/) --- ## Mental model URL: https://www.arcblock.io/en/docs/architecture/mental-model/ Hold these terms as boundaries, not as synonyms. | Term | Think of it as | Do not treat it as | | --- | --- | --- | | **AFS** | A path-addressable filesystem of resources and capabilities | A single physical database or cloud bucket | | **Provider** | A module that owns a mount path and implements operations it declares | Proof that every operation exists on every path | | **AFS UI** | An architecture lens: UI work expressed relative to AFS paths and devices | A third public authoring product equal to AUP and Web Device | | **AUP** | A declarative semantic UI tree (nodes, events, bindings, degradation) | HTML, CSS, or a site content model | | **Web Device** | An AFS provider that reads site trees and renders static HTML | An interactive AUP session or a general app runtime | | **Blocklet** | A package you author and an instance you run | Only a website, or only a UI file | | **DID / caller** | Verified identity context the runtime attaches to a request or session | A path string that happens to look like a DID | | **DID Space** | DID-scoped persistent storage mounted through AFS | A second parallel filesystem protocol | | **Data Space** | A documentation term for caller data context and views | A separate public SDK or lifecycle API | | **ARC** | The runtime and CLI shell that hosts AFS, sessions, and Blocklets | The same thing as AFS | ## How the pieces connect 1. **AFS** answers “where is the resource, and which operations does its provider support?” 2. **AFS UI** answers “when that resource is shown or edited, which device and UI contract applies?” 3. **AUP** answers interactive presentation: semantic trees, sessions, device capabilities, degradation. 4. **Web Device** answers site presentation: pages, content objects, themes, static HTML. 5. **Blocklet** answers packaging: what you ship, how you run it locally, and how it binds surfaces to AFS. 6. **Identity and data spaces** answer “who is acting, and which data view do they receive?” 7. **ARC CLI** is the operational entry for inspecting and driving those layers from a machine. ## Reading order | If you are… | Read first | | --- | --- | | New to ARC and need vocabulary | This page, then [ARC and AFS](../arc-and-afs/) | | Choosing which guide owns a task | [Product layers](../product-layers/) | | Connecting UI work to AFS paths | [AFS UI](../afs-ui/), then [AUP](/en/docs/aup/) or [Web Device](/en/docs/web-device/) | | Implementing resources or providers | [AFS](/en/docs/afs/) | | Shipping an application unit | [Blocklets](/en/docs/blocklets/) | | Handling sign-in, membership, or user data | [Identity & Data Spaces](/en/docs/identity-data-spaces/) | | Checking whether a sentence is a product promise | [Contracts and evidence](../contracts-and-evidence/) | | Chasing an old product name | [Product lineage and boundaries](../product-lineage/) | ## Contract vs explanation vs lineage - **Public contract** — behaviour you can depend on after source, tests, and a local run agree. Sibling boards own these. - **Architecture explanation** — how layers fit; useful for orientation, not a substitute for types and commands. - **Lineage** — why an older name still appears; never a full feature-equivalence claim. Internal ARC materials also use **AOS** for portable operating-system semantics (session, HTTP surface, scheduling) that ARC hosts. This public board does not treat AOS as a separate developer documentation product. When a task needs session or caller detail, use [Identity & Data Spaces](/en/docs/identity-data-spaces/) and the AUP session pages. --- ## ARC Architecture URL: https://www.arcblock.io/en/docs/architecture/overview/ ARC has several developer surfaces. They are related, but they do not share one undifferentiated contract. Use this board to choose the right layer before following a task-specific guide. | If you need to understand | Read next | Do not infer | | --- | --- | --- | | Path-based resources and provider behaviour | [AFS](/en/docs/afs/) | A global search, storage, or provider capability that has not been documented for the target runtime | | A declarative interface tree, state, or renderer boundary | [AUP](/en/docs/aup/) | That every AUP node has the same support on every target | | A static site backed by AFS paths | [Web Device](/en/docs/web-device/) | That a site layout is an interactive AUP session | | A package and instance lifecycle | [Blocklets](/en/docs/blocklets/) | That every older Blocklet Server behaviour remains part of ARC | | Identity, a DID Space, or a data-space term | [Identity & Data Spaces](/en/docs/identity-data-spaces/) | A complete remote lifecycle or trust model that has not been verified end to end | | How CLI commands map to these layers | [ARC CLI](/en/docs/arc-cli/) | That every CLI group is a separate product with its own public API | ## System map Read the stack from the bottom up when you need a resource, and from the outside in when you need a product boundary: | Layer | What it answers | Primary developer surface | | --- | --- | --- | | **AFS** | How do I address data and capabilities by path? | Operations, mounts, providers | | **AFS UI** | How do UI concerns relate to AFS resources? | Architecture lens only (this board) | | **AUP** | How do I describe an interactive interface tree? | Declarative UI contract and DSL | | **Web Device** | How do I build and render a static site? | Site directories, content, components | | **Blocklet** | How do I package and run an application? | Package, instance, local run, publish boundary | | **Identity / data spaces** | Who is calling, and which data view do they get? | Caller context, DID Space, session views | | **ARC + CLI** | How do I start, inspect, and operate the runtime? | `arc` commands and the host process | AFS is the resource and capability layer. ARC is the runtime and product shell that mounts providers, runs Blocklets, and exposes CLI and service entry points. AFS UI is not a third large authoring board equal to AUP or Web Device; it explains how those targets relate back to AFS. For ownership and the layer diagram, see [Product layers](../product-layers/). For how ARC and AFS are named separately, see [ARC and AFS](../arc-and-afs/). ## A map, not a substitute for a contract The architecture map may explain why two parts belong together. It does not turn an internal plan, an old product page, or a source directory into a public API. Treat current source, target-version tests, and a local run as the evidence for a present-tense claim. Classification rules live on [Contracts and evidence](../contracts-and-evidence/). The phrase **AFS UI** appears in ARC architecture material as a way to relate UI concerns to AFS-oriented resources. In this board it is an architectural lens, not an independent public extension API. AUP and Web Device remain separate, target-specific documentation surfaces. ## Read by task | Goal | Start here | | --- | --- | | Learn the vocabulary and reading order | [Mental model](../mental-model/) | | Separate ARC (runtime) from AFS (filesystem) | [ARC and AFS](../arc-and-afs/) | | Choose which board owns a task | [Product layers](../product-layers/) | | Place interactive UI vs static sites on AFS | [AFS UI](../afs-ui/) | | Decide whether a claim is current contract or lineage | [Contracts and evidence](../contracts-and-evidence/) | | Resolve an older ArcBlock product name | [Product lineage and boundaries](../product-lineage/) | | Collect public board links and terms | [Reference](../reference/) | ## Version boundary Facts on this board were checked against: - Installed CLI: `arc` `2.0.0-beta.28` (`arc --version`) - ARC source snapshot: `44fbd616f` (`packages/core`, `packages/aup`, `providers/runtime/ui`, `providers/runtime/web-device`, `providers/basic/did-space`, `providers/basic/members`) - Package names observed in that tree: `@aigne/afs`, `@aigne/afs-aup`, `@aigne/afs-ui`, `@aigne/afs-web-device`, `@aigne/afs-did-space` (each `2.0.0-beta.31` in source) Task-specific commands, fields, and renderer support belong on the sibling boards. Re-check those boards when your installed `arc` version differs. --- ## Product layers URL: https://www.arcblock.io/en/docs/architecture/product-layers/ Choose a layer from the problem you are solving, not from a directory name or an old product label. ## Layer map | Layer | Owns | Does not own | Developer entry | | --- | --- | --- | --- | | **AFS** | Paths, mounts, provider operations, capability declarations | Site themes, AUP primitives, Blocklet release policy | [AFS](/en/docs/afs/) | | **AFS UI** | How UI devices relate to AFS (architecture explanation) | A portable third-party device SDK promised as product | [AFS UI](../afs-ui/) (this board) | | **AUP** | Semantic UI tree, events, bindings, sessions, degradation rules | Website content model, package lifecycle | [AUP](/en/docs/aup/) | | **Web Device** | Static site trees, pages, content objects, components, HTML render | Interactive session protocol, identity lifecycle | [Web Device](/en/docs/web-device/) | | **Blocklet** | Package vs instance, local run, manifest/check, composition boundary | Core AFS op semantics, AUP node catalogue | [Blocklets](/en/docs/blocklets/) | | **Identity & data spaces** | Caller context, DID-scoped storage, session data views, membership surfaces | AFS provider authoring, site markdown pipeline | [Identity & Data Spaces](/en/docs/identity-data-spaces/) | | **ARC CLI / runtime** | Host process, service lifecycle, operational commands | Replacing the contracts of the layers above | [ARC CLI](/en/docs/arc-cli/) | ![ARC product layers: ARC hosts AFS, Blocklet, and identity; AFS projects through AFS UI into AUP and Web Device](https://raw.githubusercontent.com/ArcBlock/loop-agent-assets/main/arcblock-site/docs-architecture-20260810/architecture-product-layers-20260811064544.svg) *ARC hosts the runtime. AFS, Blocklet, and identity are primary developer surfaces. AFS UI is the lens that connects AFS resources to AUP and Web Device.* ## Decision table | You are trying to… | Correct layer | Common mistake | | --- | --- | --- | | List or write a path, mount a provider | AFS | Assuming every mount supports search or exec | | Describe buttons, forms, and state for an interactive app | AUP | Copying Web components into the AUP semantic contract | | Publish pages, posts, or a marketing site | Web Device | Treating layout AUP as a full interactive session | | Ship an installable unit with config and surfaces | Blocklet | Calling a single `.aup` file “the Blocklet” | | Know who signed in and which user data they may see | Identity | Trusting a path segment that looks like a DID | | Understand how UI and AFS fit without picking a target yet | AFS UI (this board) | Inventing a third authoring product | | Run `arc service` / `arc blocklet` / `arc afs` | ARC CLI | Treating CLI help as the only product contract | ## Composition, not collapse A Blocklet often **uses** AFS providers, AUP apps, and Web Device sites. That composition does not merge their contracts: - Web Device remains an AFS provider (`@aigne/afs-web-device`) that renders site trees. - Interactive AUP runs through the UI runtime (`@aigne/afs-ui`) and AUP types (`@aigne/afs-aup`). - DID Space (`@aigne/afs-did-space`) is a storage provider; session views project caller data into AFS paths. When two layers disagree in documentation, keep the claim on the layer that owns the behaviour, and link the other for context. Do not “average” them into one API. ## Where evidence lives | Claim type | Prefer | | --- | --- | | Present-tense operation or field | Sibling board + current source/tests for that layer | | “How layers fit” | This architecture board | | Old product name | [Product lineage](../product-lineage/) | Classification rules: [Contracts and evidence](../contracts-and-evidence/). --- ## architecture/product-layers/visuals URL: https://www.arcblock.io/en/docs/architecture/product-layers/visuals/ --- ## Product lineage and boundaries URL: https://www.arcblock.io/en/docs/architecture/product-lineage/ Older ArcBlock material still uses product names that appear next to ARC. Use this index to find the **current developer entry** and the **hard non-promises**. Status values: | Status | Meaning | | --- | --- | | `current` | Actively documented ARC surface or product dependency you can open today | | `reference implementation` | Example app or pattern used to prove a contract; not a full platform product | | `external dependency` | Capability consumed from another package or service, not re-documented here as a full ARC product board | | `historical only` | Name retained for archaeology; not a supported upgrade path | | `unresolved` | Evidence incomplete; do not invent a successor product | ## Mapping table | Old name / alias | Why readers still see it | Current ARC home | Developer entry | What is **not** promised | Status | | --- | --- | --- | --- | --- | --- | | **Discuss Kit** | Standalone discussion Blocklet; site product record `superseded` / `mergedInto: arc` | Replicated discussion data as a **reference Blocklet** (`blocklets/discuss-kit`); parts of comments/collections surfaces in Web Device / UI runtime | [Blocklets · Discuss Kit lineage](/en/docs/blocklets/discuss-kit-lineage/) · [Blocklets](/en/docs/blocklets/) | Full former board/blog/wiki/bookmark/message platform feature set | `reference implementation` | | **DID Connect** | Sign-in and credential presentation in older apps and docs | Runtime identity and membership integration (for example `@arcblock/did-connect-service` used by members provider); broader DID Connect docs remain for the protocol/SDK family | [Identity · DID Connect](/en/docs/identity-data-spaces/did-connect/) · [Identity overview](/en/docs/identity-data-spaces/) · existing DID Connect docs boards | That the former admin or user-centre UI is a stable ARC product face | `external dependency` (service/SDK) + `current` (caller/session integration on Identity board) | | **DID Spaces / DID Space** | Personal or app data space branding and docs | **DID Space** as current AFS provider (`@aigne/afs-did-space`) and user-facing space tooling (`arc space`, related Blocklets) | [Identity · DID Space](/en/docs/identity-data-spaces/did-space/) · [Identity overview](/en/docs/identity-data-spaces/) | That every remote lifecycle, trust, and multi-instance path is one finished public contract | `current` (local/provider contract as documented on Identity board) with **experimental/gap** for unproven remote lifecycle | | **Data Space** | Marketing and conceptual language around “data belonging to a DID” | **Documentation term** for caller data context and session views—not a second backend product | [Identity · Data Space term](/en/docs/identity-data-spaces/data-space-term/) | A separate public SDK, provider package, or lifecycle API named “Data Space” | `current` as terminology only | | **Media Kit** | Standalone media Blocklet; site product `superseded` / `mergedInto: arc` | Partial media publishing, rendering, delivery, and upload-related pieces around Web Device / DID Space / CDN helpers—not a single named successor product | Task-specific Web Device / Identity pages as they document media paths; do **not** assume a Media Kit board | Full former uploader, plugin suite, remote-source pipeline, asset-library UI, or migration contract | `unresolved` successor product · partial capabilities only | | **Image Bin** | Older asset/image library naming tied to media workflows | No verified full ARC equivalent product board in this documentation set | None as a first-class ARC developer board | That Image Bin features are fully present under another name | `historical only` / `unresolved` | | **Blocklet Server** (and related Server-era tooling) | Long-running packaging and hosting vocabulary | ARC **Blocklet** package/instance model and CLI (`arc blocklet`) | [Blocklets](/en/docs/blocklets/) · [ARC CLI blocklet](/en/docs/arc-cli/) | That every Server-era behaviour, API, or admin screen remains | `lineage` → current Blocklet contract is narrower and re-specified | | **AFS UI** (as if it were a product SKU) | Draft architecture documents use the phrase | Architecture lens on this board; authoring via AUP + Web Device | [AFS UI](../afs-ui/) · [AUP](/en/docs/aup/) · [Web Device](/en/docs/web-device/) | A third public authoring product or guaranteed third-party device SDK | `architecture` (not a separate product board) | ## How to use a row 1. Read **Why readers still see it** so you do not delete the name from mental models that external material still uses. 2. Open **Developer entry** for operational work. 3. Read **What is not promised** before writing migration, sales, or “feature parity” language. 4. If status is `unresolved` or `historical only`, do not invent a replacement name in public docs. ## Evidence notes (not a contract) | Name | Primary evidence used for this table | | --- | --- | | Discuss Kit | Site `content/products/discuss-kit` (`superseded`, `mergedInto: arc`); ARC `blocklets/discuss-kit` README as replicated collection reference; Web Device comments-surface code | | DID Connect | `@arcblock/did-connect-service` dependency in `providers/basic/members`; Identity board structure | | DID Space | `@aigne/afs-did-space` provider package; Identity board DID Space pages | | Data Space | Identity board terminology pages; no separate provider package named data-space | | Media Kit | Site product `superseded`; no complete Media Kit migration evidence in ARC tree for this board | | Image Bin | Name appears in historical material; no verified full successor board | Update a row only after re-checking current code. A merged PR that once added a path is not enough if the tree no longer contains it. Related: [Contracts and evidence](../contracts-and-evidence/) · [Reference](../reference/) --- ## Reference URL: https://www.arcblock.io/en/docs/architecture/reference/ This page is an **index**, not a second copy of sibling APIs. Follow the link for fields, commands, and versioned behaviour. ## Sibling boards | Board | What it owns | Entry | | --- | --- | --- | | AFS | Paths, operations, providers, catalog boundaries | [/en/docs/afs/](/en/docs/afs/) | | AUP | Declarative UI tree, DSL, sessions, degradation | [/en/docs/aup/](/en/docs/aup/) | | Web Device | Static sites, content objects, components, HTML render | [/en/docs/web-device/](/en/docs/web-device/) | | Blocklets | Package, instance, local run, publish boundary | [/en/docs/blocklets/](/en/docs/blocklets/) | | Identity & Data Spaces | Caller, DID Space, session views, boundaries | [/en/docs/identity-data-spaces/](/en/docs/identity-data-spaces/) | | ARC CLI | Command groups and operational surface | [/en/docs/arc-cli/](/en/docs/arc-cli/) | | Architecture (this board) | System map, AFS UI lens, lineage, evidence rules | [Overview](../overview/) | ## Term index | Term | One-line meaning | Start here | | --- | --- | --- | | AFS | Path-addressable resource and capability layer | [ARC and AFS](../arc-and-afs/) · [AFS](/en/docs/afs/) | | Provider | Module mounted at a path that implements declared operations | [AFS providers](/en/docs/afs/providers/) | | AFS UI | Architecture lens projecting AFS into UI devices | [AFS UI](../afs-ui/) | | AUP | Declarative semantic UI contract | [AUP overview](/en/docs/aup/) | | Web Device | AFS provider for static website trees | [Web Device overview](/en/docs/web-device/) | | Blocklet | Package and instance unit for applications | [Blocklets overview](/en/docs/blocklets/) | | Package vs instance | Immutable reusable unit vs configured deployment | [Package and instance](/en/docs/blocklets/package-and-instance/) | | DID | Identifier in verified caller context | [Identity overview](/en/docs/identity-data-spaces/) | | DID Space | DID-scoped persistent storage provider | [DID Space](/en/docs/identity-data-spaces/did-space/) | | Data Space | Documentation term for caller data context | [Data Space term](/en/docs/identity-data-spaces/data-space-term/) | | Session view | Runtime projection of caller/instance data into AFS paths | [Identity session data](/en/docs/identity-data-spaces/session-data/) | | Current contract | Present-tense claim backed by code + test/run | [Contracts and evidence](../contracts-and-evidence/) | | Lineage | Historical name mapping without feature parity | [Product lineage](../product-lineage/) | | ARC | Runtime and CLI shell hosting the layers above | [Overview](../overview/) · [ARC CLI](/en/docs/arc-cli/) | ## Package names (source tree) Useful when matching docs to repositories. Versions below are from ARC source snapshot `44fbd616f` (package.json `2.0.0-beta.31`); installed CLI used for orientation: `2.0.0-beta.28`. | Package | Role | | --- | --- | | `@aigne/afs` | AFS core | | `@aigne/afs-aup` | AUP types and pure helpers | | `@aigne/afs-ui` | Interactive UI device runtime | | `@aigne/afs-web-device` | Web Device provider | | `@aigne/afs-did-space` | DID Space provider | ## Architecture pages on this board | Page | Responsibility | | --- | --- | | [Overview](../overview/) | System map and task routing | | [Mental model](../mental-model/) | Vocabulary and reading order | | [ARC and AFS](../arc-and-afs/) | Runtime vs filesystem boundary | | [Product layers](../product-layers/) | Ownership table and layer diagram | | [AFS UI](../afs-ui/) | UI projection lens and code evidence | | [Contracts and evidence](../contracts-and-evidence/) | Status vocabulary | | [Product lineage](../product-lineage/) | Old name mapping table | If a sibling link 404s on a partial deploy, open the board root and use its nav. Do not invent alternate URLs. --- ## AUP URL: https://www.arcblock.io/en/docs/aup/ --- ## Author with DSL URL: https://www.arcblock.io/en/docs/aup/author-with-dsl/ This section explains how to maintain DSL sources, organize an app/page/shell, express values and interaction, and generate JSON artifacts only when a compatibility consumer needs them. It does not teach hand-editing JSON as the default workflow. ## Read in this order 1. [DSL source model](../dsl-source-model/) before choosing DSL-first or JSON-first inputs. 2. [App, page, and shell](../dsl-app-page-shell/) for the app-level declaration surface. 3. [Nodes, values, and sugar](../dsl-nodes-values-sugar/) and [events, navigation, and visibility](../dsl-events-navigation-visibility/) for page source. 4. [Components, loops, and i18n](../dsl-components-loops-i18n/) for compile-time reuse and locale content. 5. [Generate, lint, and migrate](../dsl-generate-lint-migrate/) to maintain artifacts without confusing formatting with validation. --- ## Caller identity and safety URL: https://www.arcblock.io/en/docs/aup/caller-identity-safety/ An AUP tree is not an access-control list. Hiding a node, naming a data path, or rendering a button never grants a caller the right to read, write, execute, or bridge that resource. ## Session substitutions have narrow semantics `$session.*` has two distinct roles: - A presentation condition can read session facts, such as `$session.authenticated` or `$session.role == owner`. - Path substitution occurs only in `src`, `bind`, and `propBind`, not in general props, events, or execution arguments. For example: ```aup input display-name bind="/user/persons/$session.did/profile/display-name" ``` The server performs per-session path substitution from own fields; missing values remain unresolved tokens rather than inventing an identity. The client cannot assert its own caller identity by sending a UI message. ## The renderer is not the authorization authority AFS/provider/runtime policy decides whether a resolved read, write, or `exec` action is allowed. UI visibility and navigation are only presentation. Likewise, validation that rejects `javascript:` or `..` is useful input safety; it does not replace service-side permission policy. Frames, bridges, remote surfaces, and write-capable flows each need their own trust, origin, session, and scope review. A same-looking button on two targets can still be backed by different authorization contexts. For embedding rules, see [Frames, bridges, and embedded surfaces](../frames-bridges-embedded-surfaces/). For data-binding semantics, see [Events, state, and bindings](../events-state-bindings/). --- ## AUP capability tour URL: https://www.arcblock.io/en/docs/aup/capability-tour-slides/ ## AUP is a semantic tree AUP is not a CSS framework and not a page template language. You author a **semantic tree** of named node types. A target device reports what it can render; the runtime degrades or refuses the rest. This deck is a **web slideshow** tour: one Markdown record, `slides: true`, hosted on Web Device docs. It shows what a **deck path** can host—not ordinary article document caps. --- ## Document caps vs deck caps | Cap profile | What it means on this site | | --- | --- | | **document** | Ordinary articles: native subset, partial time, forced degradation for interactive types | | **deck** (`DEVICE_CAPS_DECK`) | This slideshow: document natives **plus** chart/map/calendar/overlay/canvas/explorer/surface/chat shells | | **web-full** | Full interactive Web (Showcase / apps): session, write paths, multi-window | **This deck** uses `DEVICE_CAPS_DECK` (arc#4005 / #4011 / #4012). Human lock (#4006): only **rtc** and **camera-preview** are hard excludes; other surfaces ship as **readonly + authored data** demos. Ordinary articles still degrade chart→table and map→media. --- # Basic interface --- ## `view` — native Portable container. On document, tabs and steps are static UI chrome (panel switch only—no session, no `exec`). ::::view{id="aup-tour-view-tabs" mode="tabs" label="Package manager"} :::view{label="pnpm"} Install with `pnpm install`. ::: :::view{label="npm"} Install with `npm install`. ::: :::: --- ## `text` — native Ordinary Markdown body is the main `text` path. Callouts become text-admonition presentation on document. > [!NOTE] Portable copy > This callout is document content. It does not run actions or write AFS data. --- ## `media` — native Semantic media node (image path here). Same-site / whitelist rules for frames are separate. ::media{id="aup-tour-media-img" type="image" src="https://media.arcblock.io/lib/2f/2f757138def2b3fc.w1600.webp" alt="Illustrative documentation asset" caption="Document-target media illustration"} --- ## `input` — native Unbound form control on document. Typing changes only the browser control—no bind, session, or AFS write. ::input{id="aup-tour-input-name" type="text" label="Name" placeholder="Local browser only" value="Ada"} ::input{id="aup-tour-input-ack" type="checkbox" label="I understand this stays local"} --- ## `action` — native Navigation-only on document. No `exec`, no destructive confirm from a static sample. ::action{label="Open live example contract" href="/en/docs/aup/live-example-contract/" variant="primary"} ::action{label="Label only — not a navigation target" variant="secondary"} --- ## `overlay` — deck open shell Open dialog chrome on this deck (readonly). Dismiss bus / session confirm stay interactive. :::overlay{id="aup-tour-overlay-dialog" mode="dialog" title="Confirm layout" message="This shell is open by default so the slide shows real chrome—not a screenshot." open="true"} ::action{label="Understood" variant="primary"} ::: | Fact | Boundary | | --- | --- | | Deck path | **partial** open shell (arc#4012) | | Ordinary document | still **unsupported** → text | | Session dismiss / confirm bus | interactive only | --- # Structure and time --- ## `table` — native (GFM path) GFM tables render on the document target. Prefer an author-written table when the page needs data. | File | Purpose | Writes data | | --- | --- | --- | | `content.md` | Content item | No | | `layout.aup` | Page layout | No | --- ## `time` — partial Document reports **partial**. Display mode is a static snapshot, not a live clock. ::time{id="aup-tour-time-display" mode="display" value="2026-02-21T14:30:00Z"} No continuous client ticker on this path. Clock/countdown product claims belong to interactive targets after re-verification. --- ## `chart` — quarterly bar ::chart{id="aup-tour-chart-bar" variant="bar" labels='["Q1","Q2","Q3","Q4"]' data='[89,78,81,61]' label="2024" height="360px" title="Quarterly"} --- ## `map` — Paris ::map{id="aup-tour-map-paris" tileStyle="carto-voyager" center='[48.8566,2.3522]' zoom="12" height="380px" markers='[{"lat":48.8584,"lng":2.2945,"label":"Eiffel Tower"},{"lat":48.8606,"lng":2.3376,"label":"Louvre"},{"lat":48.853,"lng":2.3499,"label":"Notre-Dame"}]'} --- ## `calendar` — August 2026 ::calendar{id="aup-tour-calendar" year="2026" month="8" title="August 2026" events='[{"date":"2026-08-14","label":"Tour ship","intent":"success"},{"date":"2026-08-21","label":"Review","intent":"info"}]'} --- # Interactive surface --- ## `chat` — deck readonly + data Authored messages only. Input bar is disabled—no session bus, no write (human #4006). ::chat{id="aup-tour-chat" title="Support sample" messages='[{"role":"user","text":"Can slides host chat chrome?"},{"role":"assistant","text":"Yes — readonly shells with sample data. Live session stays on interactive targets."}]'} | Fact | Boundary | | --- | --- | | Deck path | **partial** readonly shell | | Write / session / agent runtime | **not** on this tour | | Ordinary document | still unsupported | --- ## `rtc` — excluded (human #4006) | Fact | Boundary | | --- | --- | | Deck path | **unsupported** (hard exclude) | | Shared chain | unsupported → annotated text | | What this deck does | **No RTC / camera-preview demo** | Media permissions and peer sessions are not slideshow product demos. `camera-preview` widget is excluded for the same reason. --- ## `explorer` — deck static tree Authored items only—not path-backed AFS browse. ::explorer{id="aup-tour-explorer" title="Workspace" root="/docs/aup" items='[{"name":"overview","kind":"dir"},{"name":"capability-tour-slides","kind":"dir"},{"name":"README.md","kind":"file","path":"/docs/aup/README.md"}]'} | Fact | Boundary | | --- | --- | | Deck path | **partial** static shell | | Path-backed live AFS | interactive / session only | | Pair with afs-list | static children only on docs | --- ## `editor` — native (experimental) Document registers an editor renderer as a local textarea. Typing stays in the browser—no IDE, no AFS write-back. ::editor{id="aup-tour-editor" language="json" label="Example snippet" value="{ \"ok\": true }"} Markdown attribute strings are not guaranteed to match AUP JSON booleans (`readOnly`). Prefer JSON/DSL when the prop must be strict. --- ## `canvas` — deck drawing shell Host + canvas; progressive enhance enables local pen (no AFS persistence). ::canvas{id="aup-tour-canvas" width="560" height="220" label="Sketch pad" background="#f8fafc"} | Fact | Boundary | | --- | --- | | Deck path | **partial** shell + local pen enhance | | Ordinary document | **unsupported** → media → text | | Persist strokes / multi-user | interactive only | --- ## `surface` — deck host shell Labeled host region + children. Taxonomy: primitive `surface` ≠ `wm-surface` ≠ layout surface dirs. :::surface{id="aup-tour-surface" title="Resource panel" variant="default"} Static surface body — authored children only. No session view selector on this deck. ::: | Fact | Boundary | | --- | --- | | Deck path | **partial** host shell | | Session expand / path browse | interactive only | | Confusion | do not rename site chrome as this primitive | --- ## `afs-list` — document (static children) Document can render list chrome. Path-backed live AFS data is **not** closed on public docs—use static children only. :::afs-list{id="aup-tour-afs-list-static" layout="list" itemStyle="row"} Static row one — authored as document children, not fetched. Static row two — still not an AFS path proof. ::: Empty / loading chrome without children is documented on the unit page; this tour only shows the static-children path. --- # Document-hostable widgets Widgets are **not** the 18 cross-device primitives. Deck SSR now registers focused shells for many of them (arc#4012 / #4008 / #4009). Array/object props as **JSON strings** are coerced (same as chart/map). Nested portal chrome for app-header still needs object props from DSL. --- ## `app-header` — document shell Document registers `app-header` and emits the same `.aup-app-header*` chrome classes as the interactive path. Nested `brand` / `nav` / `actions` need **object** props (Showcase / AUP DSL). Markdown directive attributes are always strings, so this slide shows the registered shell only—not a full portal header. ::app-header{id="aup-tour-app-header" variant="compact"} | Fact | Boundary | | --- | --- | | Document RENDERERS | **yes** (static) | | MD live brand/nav/actions | **not** — string attrs are not JSON-coerced | | Session / search / microBar | interactive / AFS only | Unit page: [app-header](/en/docs/aup/widgets/app-header/). Showcase: `prim-app-header`. --- ## `app-footer` — document shell Document renders a static footer. The legacy top-level `copyright` string is MD-safe and produces the bottom bar. Multi-column `brand` / `columns` / `social` need object props (same MD string-attr limit as header). ::app-footer{id="aup-tour-app-footer" copyright="© 2026 ArcBlock documentation demo — static document shell"} Unit page: [app-footer](/en/docs/aup/widgets/app-footer/). Showcase: `prim-app-footer`. --- ## `ticker` — document static Document RENDERERS force `data-mode="static"`: children separated by bullets—not a continuous scroll ticker. :::ticker{id="aup-tour-ticker"} Document surface Static children No live scroll on this path ::: Interactive scroll/flip modes stay on web-full. Unit page: [ticker](/en/docs/aup/widgets/ticker/). --- ## `broadcast` — document static shell Document RENDERERS treat `broadcast` as a view-like container: children render, live channel / director wiring does not. :::broadcast{id="aup-tour-broadcast"} Static broadcast shell — authored children only. No shared channel, no AI director, no live viewer count on document. ::: Role expansion (live-badge, lower-third, …) is interactive. Unit page: [broadcast](/en/docs/aup/widgets/broadcast/). --- ## `deck` — this tour is the host This record is already a deck: front matter `slides: true` + `layout: slides` builds the player. Document reports `deck` as **partial** host chrome—not a nested product deck inside each slide. | Fact | Boundary | | --- | --- | | Host | This capability-tour record | | Authoring | `##` slides, `---` dividers, optional media-fill bodies | | Nested `::deck` | Not required for this tour | You are inside the demo. Unit page: [deck](/en/docs/aup/widgets/deck/). Markdown slides guide: [markdown-slides](/en/docs/web-device/markdown-slides/). --- ## `frame` — document partial Sandboxed iframe via AUP `type: "frame"`. Same trust boundary as embeds: http(s) or allow-listed paths; unknown/unsafe src becomes an error or link fallback. ::frame{id="aup-tour-frame" src="https://www.youtube.com/embed/jNQXAC9IVRw" title="Me at the zoo (frame taxonomy)" aspectRatio="16 / 9"} `::embed{url=…}` is the Markdown authoring path that often compiles toward frame-shaped nodes. This slide names the **widget type** explicitly. Document capability is **partial**. Unit page: [frame](/en/docs/aup/widgets/frame/). --- ## `key-value-list` — deck shell ::key-value-list{id="aup-tour-kv" title="Release" items='[{"label":"Status","value":"Stable"},{"label":"Channel","value":"docs"},{"label":"Caps","value":"DEVICE_CAPS_DECK"}]'} Unit page: [key-value-list](/en/docs/aup/widgets/key-value-list/). Showcase: `prim-key-value-list`. --- ## `breadcrumb` — deck shell ::breadcrumb{id="aup-tour-breadcrumb" items='[{"label":"Docs","href":"/en/docs/"},{"label":"AUP","href":"/en/docs/aup/"},{"label":"Capability tour"}]'} AUP widget—not the site layout `page-breadcrumb` chrome. Unit page: [breadcrumb](/en/docs/aup/widgets/breadcrumb/). --- ## `chip` — deck shell ::chip{id="aup-tour-chip-stable" label="Stable" color="success" count="3"} ::chip{id="aup-tour-chip-info" label="Deck shell" color="info"} ::chip{id="aup-tour-chip-warn" label="Readonly" color="warning"} Unit page: [chip](/en/docs/aup/widgets/chip/). Dismiss events stay interactive. --- ## `pagination` — deck static chrome ::pagination{id="aup-tour-pagination" page="2" pageSize="10" total="47"} Buttons disabled—no page events on this tour. Unit page: [pagination](/en/docs/aup/widgets/pagination/). --- ## `tooltip` — deck shell :::tooltip{id="aup-tour-tooltip" content="Native title + visible hint for deck proof" placement="top"} Hover target (and visible tip below) ::: Unit page: [tooltip](/en/docs/aup/widgets/tooltip/). --- ## `entity-overview` — deck shell ::entity-overview{id="aup-tour-entity" title="Sample entity" cards='[{"title":"Identity","items":[{"label":"Name","value":"Tour demo"},{"label":"Kind","value":"docs"}]},{"title":"Caps","items":[{"label":"Path","value":"deck"},{"label":"Write","value":"no"}]}]'} Unit page: [entity-overview](/en/docs/aup/widgets/entity-overview/). --- ## `terminal` — deck readonly transcript ::terminal{id="aup-tour-terminal" title="arc CLI" lines='["$ arc --version","2.0.0-beta.35","$ arc blocklet check blocklets/arcblock","ok"]'} Not a live PTY / xterm WebSocket. Unit page: [terminal](/en/docs/aup/widgets/terminal/). --- ## `moonphase` — deck shell ::moonphase{id="aup-tour-moon" date="2026-08-14"} Pure math shell (no CDN). Unit page: [moonphase](/en/docs/aup/widgets/moonphase/). --- ## `globe` — world markers ::globe{id="aup-tour-globe" center='[20,0]' zoom="2" height="380px" markers='[{"lat":37.77,"lng":-122.42,"label":"SF"},{"lat":48.86,"lng":2.35,"label":"Paris"},{"lat":35.68,"lng":139.69,"label":"Tokyo"}]'} --- ## `comments-surface` — deck readonly ::comments-surface{id="aup-tour-comments" title="Thread sample" comments='[{"author":"Ada","body":"Readonly comments prove the type hosts on deck.","at":"2026-08-14"},{"author":"Grace","body":"Write path and session stay off this tour.","at":"2026-08-14"}]'} Human #4006: data demo OK; no write. Live article mount is a separate site toggle. --- ## `wm` — single-panel shell :::wm{id="aup-tour-wm" title="Panel"} Single-panel window chrome for deck geometry (1280×720). Not multi-window desktop. ::: Human #4006: single-panel OK; full desktop geometry stays Showcase `wm-desktop.aup`. --- ## `agent` — deck readonly (chat alias) ::agent{id="aup-tour-agent" title="Assistant sample" messages='[{"role":"user","text":"What can deck host?"},{"role":"assistant","text":"Readonly agent chrome with sample turns—no agent runtime on this tour."}]'} Same shell as chat. No AFS write / agent loop. --- ## `wm-surface` — same single-panel shell :::wm-surface{id="aup-tour-wm-surface" title="Surface panel"} Same SSR as `wm`. Taxonomy: widget `wm-surface` ≠ primitive `surface`. ::: --- ## `xeyes` — static gaze ::xeyes{id="aup-tour-xeyes" eyes="2" title="xeyes" size="md"} Mouse tracking stays interactive. Deck hosts the chrome. --- ## `searchable-dropdown` — closed list ::searchable-dropdown{id="aup-tour-dropdown" placeholder="Pick a runtime" value="bun" options='[{"label":"Bun","value":"bun"},{"label":"Node","value":"node"},{"label":"Workers","value":"workers"}]'} Filter / onChange stay interactive. --- ## `afs-stat` — label + value ::afs-stat{id="aup-tour-stat" label="Open PRs" value="12"} --- ## `afs-preview` — path + snippet ::afs-preview{id="aup-tour-preview" title="README" path="/docs/aup/README.md" preview="# AUP\nSemantic tree. Device reports caps."} --- ## `afs-dropzone` — dashed host ::afs-dropzone{id="aup-tour-dropzone" label="Drop into /inbox" target="/inbox"} Ingest / grant PUT stay off this tour. --- ## `natal-chart` — planets table ::natal-chart{id="aup-tour-natal" variant="planets-table" data='{"planets":{"Sun":[45.2],"Moon":[120.5],"Mercury":[12]}}'} Astrochart CDN stays on web-full. --- ## `finance-chart` — candle table ::finance-chart{id="aup-tour-finance" variant="candlestick" data='[{"time":"2026-08-12","open":10,"high":12,"low":9,"close":11},{"time":"2026-08-13","open":11,"high":13,"low":10,"close":12},{"time":"2026-08-14","open":12,"high":12.5,"low":11,"close":11.5}]'} TradingView stays interactive. --- ## `skills` — authored names ::skills{id="aup-tour-skills" items='[{"name":"issue-audit"},{"name":"land"},{"name":"verification"}]'} Live registry stays off this tour. --- ## `text-highlight` — marks ::text-highlight{id="aup-tour-highlight" content="Deck can host ==highlighted== phrases without an iframe."} --- ## `type-block` — authored DSL ::type-block{id="aup-tour-type-block" mode="shuffle" content="AUP is a semantic tree."} Iframe type-block runtime stays interactive. --- ## `hero-widget` — title + desc ::hero-widget{id="aup-tour-hero" title="Capability tour" desc="Readonly host for the WebGL/iframe hero." style="cube"} --- ## `webgl-hero` — GPU placeholder ::webgl-hero{id="aup-tour-webgl" title="WebGL hero"} --- ## `progress-bar-3d` — CSS stand-in ::progress-bar-3d{id="aup-tour-progress" value="64" title="Load"} --- ## `photo-story` — stills ::photo-story{id="aup-tour-photos" title="Plates" items='[{"src":"plates/01-bridge.jpg","alt":"Bridge"},{"src":"plates/02-ridge.jpg","alt":"Ridge"}]'} --- ## `text-image-expand` — pair ::text-image-expand{id="aup-tour-tie" src="plates/03-harbor.jpg" text="Harbor plate. Expand/hover stays interactive."} --- ## `scroll-explainer` — stacked steps ::scroll-explainer{id="aup-tour-scroll" title="How a slide ships" items='[{"title":"Author Markdown"},{"title":"Deck SSR shell"},{"title":"Enhance where JS exists"}]'} --- ## `block-revealer` — already open :::block-revealer{id="aup-tour-revealer" title="Revealed"} Enter/scroll reveal stays interactive. This slide starts open. ::: --- ## `post-editor` — readonly ::post-editor{id="aup-tour-post" title="Draft" value="Readonly chrome. Publish path stays off this tour."} --- ## `share-panel` — URL chrome ::share-panel{id="aup-tour-share" title="Share" url="https://new.arcblock.io/en/docs/aup/capability-tour-slides/" text="AUP capability tour"} Native share sheet / QR stay interactive. --- ## `provider-card` — catalog chrome ::provider-card{id="aup-tour-provider" name="DID Space" description="Deployment storage. Card chrome only on this deck."} --- ## `connection-gate` — status ::connection-gate{id="aup-tour-gate" title="Connect" status="disconnected"} Auth/connect stay off the slideshow. --- ## `blocklet-embed` — address only ::blocklet-embed{id="aup-tour-embed" title="Embedded blocklet" src="https://new.arcblock.io/"} Nested live session stays off this tour. --- ## `auto-surface` — host :::auto-surface{id="aup-tour-auto-surface" title="Auto surface"} Fixture chrome. Session expand stays interactive. ::: --- ## `auto-fire` — no fire ::auto-fire{id="aup-tour-auto-fire" title="auto-fire" exec="/dev/agent/.actions/run" dedupKey="tour"} Would exec on mount. Deck: no fire. --- ## `url-default` — no navigation ::url-default{id="aup-tour-url-default" title="url-default" match="/app/today" redirect="/app/today/2026-08-14"} Canonicalize-on-mount stays off this tour. --- # Markdown surface --- ## Admonition (GFM callout) Same path as `text` admonition—shown again as an authoring surface you type in Markdown. > [!TIP] Prefer same-line titles > A bare marker uses locale defaults; an explicit title on the marker line always wins. > [!WARNING] Unknown markers > `[!FIXME]` stays an ordinary blockquote, not callout chrome. --- ## Steps (`::::steps`) Tutorial chrome lands on document `view` rendering. Outer fence must wrap each `:::step`. ::::steps :::step{title="Name the target"} Document vs web-full first—then pick primitives the target reports. ::: :::step{title="Demo or label"} Native → live MD sample. Unsupported → one honest “not on document” slide. ::: :::: --- ## YouTube partial Prose keeps the embed partial — normal deck padding, no `data-media-fill`. Supported providers render as a sandboxed frame; unrecognized URLs stay ordinary links. ::embed{url="https://youtu.be/jNQXAC9IVRw"} This is the `frame` / embed path—not a general privileged iframe API. --- ## GFM table (MD structure) Author tables in ordinary Markdown when the document needs data. Live chart on **this deck** is a separate experimental node (generic directive)—not a general MD chart contract for all docs. Do not smuggle a chart through a GFM table. | Cap | document article | this deck (`DEVICE_CAPS_DECK`) | web-full | | --- | --- | --- | --- | | `table` | native | native | webview | | `chart` | unsupported → table/text | partial shell (Chart.js) | chart | | `map` | unsupported → media/text | partial shell (Leaflet) | map | --- ## Image (Markdown structure) Inline images are a structure path distinct from `::media`, but both are document-reachable media presentation. ![Illustrative documentation asset](https://media.arcblock.io/lib/2f/2f757138def2b3fc.w1600.webp) Prefer `::media` when you need caption / type props as an AUP node; use `![alt](src)` for ordinary article figures. --- ## Link card + navigation action Cards are Markdown directives that compose with `action` for navigation-only CTAs. ::link-card{title="Primitive taxonomy" description="18 cross-device primitives vs 42 Web-only widgets—keep the layers separate." icon="book" href="/en/docs/aup/primitive-support-matrix/"} :::action-card{title="Device caps and degradation" description="Shared chains, document article policy, and deck chart/map shells." icon="layers"} ::action{label="Open degradation guide" href="/en/docs/aup/device-capabilities-degradation/" variant="primary"} ::: --- # Deck media host --- ## One stage · many media modes The deck is a **1280×720 media host**, not just prose cards. | Mode | Feel | | --- | --- | | **Single plate** | One photo, edge-to-edge | | **Mosaic** | Bento tiles fill the stage | | **Grid** | Equal tiles fill the stage | | **Stage / video** | 16:9 box, full-bleed loop, YouTube | | **Tweet clamp** | Tall embed scrolls *inside* the stage | Next pages: **one effect each** — visual first. --- ## Single plate ::media{type="image" src="plates/01-bridge.jpg" alt="Bridge"} --- ## Mosaic ::gallery{folder="plates" layout="mosaic"} --- ## Grid ::gallery{folder="plates" layout="grid" cols="3"} --- ## Sized stage ::gallery{folder="plates" layout="stage" ratio="16:9" width="100%"} --- ## Full-bleed · plates ::gallery{folder="video-plates" layout="stage"} --- ## Full-bleed · YouTube ::embed{url="https://youtu.be/jNQXAC9IVRw"} --- ## Tweet clamp ::embed{url="https://x.com/arcblock_io/status/1955367769672950142"} --- ## What this deck proves - **One Markdown record** → player + reading transcript (`slides: true`) - **Deck ≠ document article** — interactive shells on `DEVICE_CAPS_DECK` - **Hard excludes** — only `rtc` and camera-preview (#4006) - **Widgets** — one focused readonly+data slide each (arc#4009); web-full stays richer - **Media host** — single · mosaic · grid · stage · full-bleed · tweet --- ## Keep exploring ::action{label="Primitive taxonomy" href="/en/docs/aup/primitive-support-matrix/" variant="primary"} ::action{label="Widgets hub" href="/en/docs/aup/widgets/" variant="secondary"} ::action{label="Device capabilities" href="/en/docs/aup/device-capabilities-degradation/" variant="secondary"} ::action{label="Markdown slides" href="/en/docs/web-device/markdown-slides/" variant="secondary"} --- ## CLI diagnostics URL: https://www.arcblock.io/en/docs/aup/cli-diagnostics-reference/ Run diagnostics from the smallest relevant directory. Each command has a distinct responsibility: | Command | Primary boundary | Writes? | Failure means | | --- | --- | --- | --- | | `arc dsl format --check` | Formatting drift | No | Source would be reformatted | | `arc dsl format --write` | Formatting normalization | Yes | The command could not safely format source | | `arc dsl lint ` | DSL static authoring issues | No | Error-level lint findings; warnings still need review | | `arc dsl validate ` | Parsed AUP/DSL semantics | No | A source/configuration contract is invalid | | `arc dsl generate --check` | Compatibility-artifact drift | No | Materialized output would differ | | `arc dsl generate --write` | Compatibility-artifact materialization | Yes | Output could not be generated safely | | `arc blocklet check ` | Combined source checks, Content Space when present, and selected profile structure | No | The declared blocklet shape is invalid for that check | `dsl validate` scans AUP sources and Web layouts, including `pages/**/layout.aup`, object-level `content/**/layout.aup`, and `layouts/*.aup`. A passing scan does not inspect reader-facing visual hierarchy or all runtime target behavior. ## A simple acceptance order ```bash arc dsl lint . arc dsl validate . arc blocklet check . arc blocklet build . arc blocklet run . ``` The first four establish increasingly broader static/build evidence. The final command is where a person or a clean acceptance agent opens the actual URL, checks the intended interaction, and records what was observed. I18n migration is a separate narrow maintenance operation. It does not automatically translate content or reliably resolve every historical locale structure; review its diff rather than treating it as a generic upgrade command. For source-generation detail, see [Generate, lint, and migrate](../dsl-generate-lint-migrate/). Web-site diagnostic categories remain target-specific and are outside this AUP reference. --- ## Core concepts URL: https://www.arcblock.io/en/docs/aup/concepts/ This section follows runtime semantics: how an AUP tree expresses intent, how events and data change it, how a session delivers change to a renderer, and how missing device capability produces an explicit degradation or refusal. ## Read in this order 1. [Semantic tree](../semantic-tree/) for the node/data/child model. 2. [Events, state, and bindings](../events-state-bindings/) for declared interaction and data directions. 3. [Sessions, patches, and scenes](../sessions-patches-scenes/) for the interactive delivery path. 4. [Device capabilities and degradation](../device-capabilities-degradation/) for target-specific support rather than assumed portability. 5. [Caller identity and safety](../caller-identity-safety/) before treating a UI condition as authorization. --- ## Custom primitives and Web widgets URL: https://www.arcblock.io/en/docs/aup/custom-primitives-web-widgets/ The current source has two different registries: - **18 shared primitives** are the cross-device vocabulary used by capability negotiation. - **42 Web-only widgets** are available in the Web runtime but are not a portability promise for other renderers. Those counts describe the current checkout, not a permanent API-size guarantee. Before making a portability statement, use the primitive name and target support matrix rather than a widget’s visual resemblance to a native control. ## Add a custom name carefully A blocklet can declare custom primitive names, or ARC can scan a Web Component manifest so DSL and structural validation accept those names. That extends the set of names an author may use. It does **not** create a renderer implementation on every device, add a degradation chain, or grant the component a privileged data/action capability. Use a custom type when the target and its component contract are deliberately part of the product. Use a shared primitive when the intended meaning fits an existing portable contract. Do not call a Web-only widget a “primitive” merely because a page needs it. ## Keep three component concepts separate | Concept | Owns | Does not imply | | --- | --- | --- | | AUP shared primitive | Portable semantic intent | Identical native presentation everywhere | | Web widget | A Web runtime capability | Support by every device renderer | | Web Device component | Reusable site HTML/CSS/interaction presentation | A new cross-device AUP primitive | Unknown/custom types without a degradation chain pass through unchanged. They are not automatically converted to text. Plan a concrete target acceptance test before publishing a custom-type example. See [Primitive taxonomy and evidence](../primitive-support-matrix/). The site-component layer belongs to the target's Web Device documentation, not to this portable-primitive reference. --- ## Device capabilities and degradation URL: https://www.arcblock.io/en/docs/aup/device-capabilities-degradation/ Capability is neither guessed by a page author nor invented solely by a renderer. The client/device reports `DeviceCaps` during session handshake; AUP defines the capability shape and shared degradation chains; a concrete target presents from the reported capability. `DeviceCaps` contains at least `platform`, `formFactor`, and a `primitives` map. Current primitive-capability values are: | Value | Meaning | | --- | --- | | `native` | Fully implemented by a native renderer | | `webview` | Fully implemented by a WebView renderer | | `partial` | Renderable, with some unsupported props | | `unsupported` | Cannot be directly rendered; try the shared degradation chain | Display, input, and features can add device context. They are not authorization switches that let an author bypass target renderer support. ## Primitives with an explicit chain today The shared degradation table in `2.0.0-beta.25` currently defines only these nine chains: | Original type | Try in order | | --- | --- | | `globe` | `map` → `media` → `text` | | `chart` | `table` → `text` | | `map` | `media` → `text` | | `editor` | `input` → `text` | | `canvas` | `media` → `text` | | `rtc` | `unsupported` | | `calendar` | `table` → `text` | | `time` | `text` | | `overlay` | `text` | The current algorithm treats `native`, `webview`, and `partial` as supported. If a chain reaches `unsupported` or finds no supported fallback, the tree receives an explicit text/unsupported marker. That is not a guarantee of an equivalent experience. In particular, an unknown or custom type with no explicit degradation chain currently passes through unchanged rather than automatically becoming `text`. “There is degradation” therefore does not mean every node displays safely on every device. ## Chart on the static document target `chart` is a cross-device primitive and can render with Chart.js on a full interactive Web surface. The **static document** target used for site docs is different: | Fact | Current boundary | | --- | --- | | Document capability | `DEVICE_CAPS_DOCUMENT` does **not** list `chart`, so the value is `unsupported` | | Shared chain | `chart` → `table` → `text` | | What you get on document | A **table**, not a live chart. No Chart.js, canvas, or CDN load on this path | | Data reshape | When the runtime includes the static reshape ([arc#3447](https://github.com/ArcBlock/arc/issues/3447) / [arc#3458](https://github.com/ArcBlock/arc/pull/3458)), inline `labels` / `datasets` (or single-series `data`) become real table columns and rows instead of an empty “No data” table | | Version gate | The published version string `2.0.0-beta.28` is **before** that reshape commit. A CLI that only reports `2.0.0-beta.28` but is built from a later checkout may already reshape; a pure pre-reshape build may still show “No data”. Treat **live chart in docs** as unsupported until a release both declares document chart capability (or a dedicated document chart renderer) **and** is re-verified on this site | | Markdown authoring | There is **no** defined `::chart` Markdown directive. Do not invent one in site content | | Docs sample policy | Public docs must **not** present a live chart sample as a document capability. Prefer a plain Markdown or AUP `table` when the page needs data on the static target | Measured on this documentation baseline with `arc --version` `2.0.0-beta.28` against a local Arc checkout that already contains the reshape: document still reports `chart` as `unsupported`, and `renderToHtml` of an inline bar chart yields a populated semantic `` (including caption when `title` is set), not a chart graphic. Full evidence lives in the internal capability matrix (`docs/aup/capability-matrix.md` §0.6). ## Primitives versus Web widgets There are currently 18 cross-device primitives and 42 Web-only widgets. A Web-only widget can have a renderer in the Web runtime but is not part of the cross-device `DeviceCaps.primitives` table. When you use `terminal`, `frame`, `breadcrumb`, or a similar widget, treat it as a Web-target capability and accept it in a browser rather than assuming a mobile/terminal fallback. ## Slides / deck path (web) Ordinary **document** pages use `DEVICE_CAPS_DOCUMENT`. A tree that contains a **deck** (Markdown `slides: true`) may use `DEVICE_CAPS_DECK` so selected interactive types keep progressive-enhance / readonly shells instead of the article degradation chain: **chart**, **map**, **calendar**, **overlay**, **canvas**, **explorer**, **surface**, **chat**, and **globe** (map-shell variant) under arc#4005 / #4011 / #4012. That path is **not** a general product claim that every document page can host live Chart.js or Leaflet — ordinary articles still degrade those types. Markdown directive attributes remain strings; deck demos that pass JSON arrays as attributes also need runtime coercion (arc#4013). ## Author acceptance order 1. Start with primitives the target you support explicitly reports. 2. When using one of the nine degradable types, write down the text/table/media fallback that remains acceptable. 3. Open the same tree on a real target and inspect presentation and any user-visible degradation marker. 4. Give a Web-only widget its own Web acceptance; do not copy that success into a cross-device conclusion. For the full name taxonomy, read [Primitive taxonomy and evidence](/en/docs/aup/primitive-support-matrix/). For the transport boundary of interactive updates, read [Sessions, patches, and scenes](/en/docs/aup/sessions-patches-scenes/). --- ## App, page, and shell URL: https://www.arcblock.io/en/docs/aup/dsl-app-page-shell/ An `app` declaration is the DSL’s authoring manifest. It can name a default page, tone/palette/mode/branding values, wrapper or shell, locales, page order, page discovery, overrides, and explicit pages. It compiles to AUP configuration; it is not a second runtime or a replacement for blocklet routing. ## A small app with an inline page ```aup app "Nimbus" { default home locales [en, zh] shell { header { brand "Nimbus" -> href "/" action "Home" -> page home } footer "Nimbus" } page home "Home" { view { h1 "Welcome" } } } ``` `shell` and an explicit `wrapper "wrapper.json"` cannot be combined. A shell generates wrapper material that places the page content slot between header and footer; it is a concise app frame, not a full application framework. ## Choose one page-discovery form deliberately Pages may be defined inline, declared as an external tree/settings/scaffold, or discovered through a limited declaration such as `pages from "pages/*.aup"`. That latter form is resolved by ARC’s page parser; it is not a general glob language that works outside the runtime. Inline pages compile to `pages/.json`. Named page navigation is checked against declared pages, which makes a missing page a source problem rather than a browser surprise. The currently built-in recipe names are narrow (`settings-shell`, `workspace-shell`, `marketing-site`, and `scaffold-app`). Do not document an arbitrary recipe name as available until the target runtime has accepted it. Next, read [Nodes, values, and sugar](../dsl-nodes-values-sugar/) and [Events, navigation, and visibility](../dsl-events-navigation-visibility/). --- ## Components, loops, and i18n URL: https://www.arcblock.io/en/docs/aup/dsl-components-loops-i18n/ These three features solve different problems. Do not use a compile-time loop where the product needs a live data list, or use a visibility condition where the product needs authorization. ## Components are compile-time composition `component name(params...) {}` defines a page-level macro. `use name(...)` supports positional arguments, named arguments, and defaults. If the component has explicit IDs or internal event targets and is used more than once, `use ... as namespace` prefixes the expansion so each use remains distinct. ## Static `for` is not a data query ```aup page index { component card(page, label="Open") { button "card-$page" $label primary -> page $page } view { for page in [home, settings] { use card($page) } } } ``` `for x in [...] {}` expands a static array at compile time, with `$index`, `$first`, and `$last` in context. It is not a source-driven or live data list. Use `afs-list`/`repeat` for a runtime list whose data path and target behavior are explicitly supported. `include`/`partial` require a runtime include resolver; `import` brings in component definitions only and does not create page nodes. Include/component expansion has a default depth boundary and reports cycles rather than trying to resolve them indefinitely. ## Localize source, not guesswork After an app declares `locales [en, zh]`, a page can include one `i18n {}` block: ```aup i18n { title { en "Welcome" zh "欢迎" } } h1 :title ``` The shorthand compiles to a translation key. A key can also reference existing source material. Missing inline translations can fall back during rendering, while strict locale checks can report coverage gaps; an unknown i18n key fails. This feature does not automatically translate copy or replace Web Device’s localized content-object system. For data-driven list semantics, see [Events, state, and bindings](../events-state-bindings/). Site content objects and their locale files belong to the target's Web Device layer, not to this DSL page. --- ## Events, navigation, and visibility URL: https://www.arcblock.io/en/docs/aup/dsl-events-navigation-visibility/ The DSL `->` is not a universal arrow. The current parser treats it as button/action click shorthand; other nodes need an explicit `on -> ...`. First decide whether you need an in-page update, AUP page navigation, an AFS action, or browser URL navigation. ## Current action shapes ```aup button open "Open" primary -> page details button load "Load" primary -> set viewer src "/items/42" button bump "Bump" primary -> set dial state {value: 7, dirty: true} action -> exec "/.auth/logout" action -> navigate "/.well-known/service/login" ``` Their boundaries are: | DSL form | Compiled intent | | --- | --- | | `-> page details` | `set.page` on `_root`, switching to a named AUP page | | `-> set src ...` | Update the target node's data path | | `-> set state ...` | Update the target node's UI-local state | | `-> exec ...` | Call an AFS action | | `-> navigate ...` | Client-side browser-level URL navigation | The old JSON `page: "details"` is a deprecated shortcut. New DSL should use `-> page details`, so generated output uses the current `_root` + `set.page` form. When one update must set `src`, `props`, or multiple state fields together, use complete `events={...}`. One-line sugar does not cover every compound update. Make the event object explicit rather than combining competing click handlers for one logical action. ## Visibility is not yet one fully typed cross-device promise The current DSL compiler accepts and emits a `visible` condition field, and Showcase DSL uses it. At the same time, the base `AUPNode` TypeScript interface does not list `visible` as a universal field. This documentation therefore treats it as a conditional field supported by the DSL/runtime at this target version, not a guarantee that every renderer has identical visibility semantics. When using it: 1. Keep the core tree understandable without the visibility condition. 2. Accept both true and false conditions in the real target renderer. 3. Do not use hidden UI as authorization. A hidden control must not be the only barrier to an unauthorized AFS action. For the full event/state/caller-scope boundary, read [Events, state, and bindings](/en/docs/aup/events-state-bindings/) and [Caller identity and safety](/en/docs/aup/caller-identity-safety/). --- ## Generate, lint, and migrate URL: https://www.arcblock.io/en/docs/aup/dsl-generate-lint-migrate/ These commands answer different questions. A green command is useful evidence, but it is not a substitute for running the app in its intended renderer. ```bash arc dsl format ./hello-aup --write arc dsl lint ./hello-aup arc dsl validate ./hello-aup arc dsl generate ./hello-aup --check ``` ## Read each result correctly | Command | What it examines | Does it write? | What a green result does **not** prove | | --- | --- | --- | --- | | `format --write` | DSL source formatting | Yes | That the source is valid or runnable | | `format --check` | Whether formatting would change files | No | That generated artifacts are current | | `lint` | Authoring-level DSL problems | No | That the full app configuration and target renderer agree | | `validate` | Parsed DSL/configuration semantics | No | That a browser/device presents the intended interaction | | `generate --check` | Whether compatibility artifacts would change | No | That a source-first app must keep JSON on disk | | `generate --write` | The same artifacts | Yes | That the generated app passed a runtime acceptance test | On a fresh `minimal-app` scaffold in ARC `2.0.0-beta.25`, `format --write` rewrites three DSL sources. `format_changed` is the diagnostic from `format --check` when formatting would alter files; it is not the normal success result of the `--write` command. ## Treat generated JSON as compatibility work DSL-first apps can expose compatible JSON virtually. A project only needs physical JSON when a specific compatibility consumer asks for materialized files. Use the following decision order: 1. Keep the `.aup` source authoritative. 2. Run `generate --check` in CI or before handing the project to a consumer that expects generated files. 3. Run `generate --write` only when that consumer actually needs the physical artifact, then review the diff like any other derived output. 4. Do not delete a JSON-first app merely to make it look DSL-first; JSON remains a supported source form. For an AUP app configuration, a present `.aup/app.aup` takes precedence. If it is absent, ARC can read `.aup/app.json` as source. If the DSL file exists but is invalid, ARC fails rather than silently falling back to old JSON. That makes an invalid source visible instead of masking it with a stale artifact. ## Use a narrow migration loop When converting an existing source, do not change source language, UI behavior, and deployment boundary in one step: 1. Format, lint, and validate the current source. 2. Generate in check mode and inspect what would differ. 3. Materialize only if a real downstream consumer needs it. 4. Run `arc blocklet check` for the declared profile, then run the blocklet locally and inspect the actual target. See [CLI diagnostics](../cli-diagnostics-reference/) for the command boundary and [Sources, artifacts, and JSON compatibility](../source-artifact-json-compatibility/) for loader priority. --- ## DSL language reference URL: https://www.arcblock.io/en/docs/aup/dsl-language-reference/ This is a working language map, not a promise that every name found in a historical Showcase is a released, portable API. The current parser/compiler and positive/negative tests are the source of truth for exact grammar. ## 1. App manifest Use `app` to declare app-level defaults, pages/page discovery, ordering, overrides, wrapper or shell, locales, and presentation values. `shell` and an explicit wrapper are mutually exclusive. See [App, page, and shell](../dsl-app-page-shell/). ## 2. Page source Within a page, the main authoring forms are: | Form | Purpose | | --- | --- | | `page` | Names a source page and its tree | | `i18n {}` | Declares the page’s inline locale table | | `component` / `use` | Compile-time reusable composition | | `include` / `partial` / `import` | Resolver-backed source reuse, with different scope limits | | `for` | Compile-time expansion of a static array | | AUP node | The emitted semantic UI tree | ## 3. Node common tail Most node authoring combines an optional ID, an inline value, `key=value` props, children, and one of the data/interaction clauses: ```text from # source show if # presentation condition on -> # explicit event -> # action/button click shorthand only ``` Use `-> page ` for named-page navigation and `-> set props|src|state ...` for the supported local update shorthand. Values are data literals, not arbitrary JavaScript expressions. ## 4. Compilation and checks The DSL compiles to an AUP tree, app/page JSON compatibility material, and inline locale tables. Use formatting, lint, validation, optional generation, and blocklet checks in their respective roles; no single one is a browser/device acceptance result. ```bash arc dsl format . --check arc dsl lint . arc dsl validate . ``` Keep cross-renderer primitive support out of this grammar page. That belongs to [Primitive taxonomy and evidence](../primitive-support-matrix/); it prevents a convenient DSL spelling from being mistaken for universal device support. --- ## Nodes, values, and sugar URL: https://www.arcblock.io/en/docs/aup/dsl-nodes-values-sugar/ DSL node sugar keeps authoring concise; it does not create a separate renderer contract. The compiler lowers common forms into semantic AUP nodes: | DSL form | Compiles to | | --- | --- | | `stack`, `row`, `grid`, `card` | `view` | | `h1`, `h2`, `h3`, `p`, `badge` | `text` | | `button`, `tab` | `action` | | `repeat` | `afs-list` | An inline literal becomes `text.content` or `action.label`; `key=value` supplies properties. Values can be strings, numbers, booleans, `null`, objects, or arrays. The DSL has compile-time `+` and `*` operations and macro substitution; it is not a general JavaScript expression language. ## Data, visibility, and events ```aup button rename "Rename" primary -> set headline props {content: "Renamed"} button load "Load" primary -> set list src "/modules/index" ``` `from` sets `src`; `show if` sets `visible`; and `on -> ...` can bind an explicitly named event. A bare `->` is reserved for the click shorthand on `action`/`button`. `show if` is presentation control, not authorization. A hidden tree is not an AFS access policy. ## Be explicit when another node refers to an ID The compiler can infer stable IDs when authors omit them. When an event target, patch, test anchor, or another node must name the target, give it an explicit ID. It makes the source easier to review and avoids accidental identity changes during a refactor. `-> page` lowers to the current root update `{ target: "_root", set: { page } }`; use the DSL form rather than writing legacy top-level page fields into new source. For runtime semantic fields, see [Nodes, events, and messages](../node-event-message-reference/). For compile-time components and loops, continue to [Components, loops, and i18n](../dsl-components-loops-i18n/). --- ## DSL source model URL: https://www.arcblock.io/en/docs/aup/dsl-source-model/ AUP DSL is the authoring surface for a DSL-first app. For that kind of app, the runtime reads `.aup/app.aup` first and reads `.aup/app.json` as JSON source only when DSL is absent. When a source exists but cannot parse, fix the DSL instead of expecting JSON to mask the failure. JSON-first apps remain a supported input form. `minimal-app` identifies these files as sources an author should change: | Source | Purpose | |---|---| | `.aup/app.aup` | App tree and page registration | | `pages/**/layout.aup` | Web page layout | | `.web/components/**/component.dsl` | Source for a Web-component manifest | | `agents/**/agent.dsl` | Source for an agent manifest | | `seed/settings/**/settings.aup` | Settings source | Some JSON is generated by the recipe immediately; other `.aup` compatibility artifacts materialize only after `arc dsl generate --write`. Do not decide whether a file is authoring source just because it currently exists on disk. Inspect the recipe’s `source DSL`, `AFS data`, and `generated compatibility artifacts` sections first. This model remains version-bound. Runtime compilation can expose AUP app/page/wrapper JSON virtually; only a compatibility consumer that explicitly needs on-disk output requires materialized `.aup/*.json`. Current source and the DSL Showcase both show that some runtime/reviewer workflows still consume JSON, so run the checks required by that consumer before deleting or ignoring an artifact. --- ## Events, state, and bindings URL: https://www.arcblock.io/en/docs/aup/events-state-bindings/ “A value changed” is not one kind of operation in an interface. AUP distinguishes reading data, writing data back, projecting data into a prop, storing UI-local state, and handling a user event. Choose the contract first so the renderer, AFS scope, and tests know who owns what. ## Four data/state relationships | Form | Current meaning | Do not infer | | --- | --- | --- | | `src` | A read-only AFS data path | Automatic write authority | | `bind` | A read/write AFS binding, often used by input | Every path is readable and writable | | `propBind` | A server-managed read-only `dotted prop path → AFS path` binding | A renderer itself calls AFS or manages subscriptions | | `state` | A UI-local state object | All state is necessarily client-only or persistent | `propBind` resolves its initial value before first render and updates props through a patch when its source changes. Input validation is explicitly marked as client-only transient state; the lifecycle of other `state` must be accepted against the behavior of its app/renderer rather than assumed from one blanket rule. The current DSL can compile `from "path"` to `src`, and accepts `bind=...`, `propBind={...}`, `state={...}`, and `events={...}`. Path validation rejects `javascript:` and `..`; that is not a promise that an arbitrary AFS path receives access authority. ## Three results of an event An `AUPEvent` can: 1. Call an AFS action with `exec` and optional `args`. 2. Update a node's `src`, `props`, `state`, or `events` through `target` + `set`. 3. Perform client-side browser-level URL navigation through `navigate`. The current preferred named-page navigation sets `target` to `_root` and uses `set: { page: "name" }`. The older JSON form `page: "name"` is deprecated. New DSL can use `-> page details`, which compiles to the preferred root/set form. These DSL snippets use shapes accepted by the current parser: ```aup button open "Open" primary -> page details button load "Load" primary -> set viewer src "/items/42" button bump "Bump" primary -> set dial state {value: 7, dirty: true} action -> exec "/.auth/logout" action -> navigate "/.well-known/service/login" ``` `->` is click sugar for buttons/actions. Other nodes should explicitly use `on -> ...`. When one update needs a compound set, such as `src` and `props` together, use complete `events={...}` rather than expecting one-line sugar to express every combination. ## Accept observable behavior First verify one thing: does an input or action produce the intended patch or page change? Then verify that an AFS action runs only in the correct caller scope. Finally inspect renderer loading, validation, or animation state. Collapsing all three into “the button can be clicked” hides errors in read/write authority, update targets, and navigation semantics. Read [Sessions, patches, and scenes](/en/docs/aup/sessions-patches-scenes/) next for how updates propagate through an interactive session. --- ## Example: AFS data binding URL: https://www.arcblock.io/en/docs/aup/example-afs-data-binding/ The current DSL Showcase contains a `list-template` source example built around `afs-list`. It is useful because it shows the opposite of a compile-time `for`: the item template is rendered from a runtime data list rather than expanded from a literal array. ## Read the example at the correct layer - `afs-list` expresses a runtime list/template intent. - The data path is resolved through the runtime/AFS path boundary. - A renderer and session still determine whether the result can be presented. - Readability of a path does not imply write permission, `exec` permission, or a portable renderer experience. Do not convert the sample into a generic promise that a particular legacy alias or sample path exists in every blocklet. Use the current product’s declared path and a real caller/session when testing. ## Acceptance sequence 1. Declare the smallest read-only source path for the app under test. 2. Run source validation and the relevant blocklet checks. 3. Start the registered app locally with a caller/session that is entitled to the path. 4. Observe the item template, an empty result, and a denied/unavailable result distinctly. 5. Only add bindings or actions after the read boundary is understood. This page deliberately does not turn a Showcase source file into a public data endpoint. For source syntax, see [Nodes, values, and sugar](../dsl-nodes-values-sugar/); for authorization, see [Caller identity and safety](../caller-identity-safety/). --- ## Example: interaction flow URL: https://www.arcblock.io/en/docs/aup/example-interaction-flow/ The current DSL Showcase contains an `overlays` source example with `open`/`close` behavior and state. It is useful for explaining an interaction flow as a sequence of semantic intent: 1. A visible control emits an explicit event. 2. The event targets a named node/state change. 3. The next tree/presentation is produced by the runtime and target renderer. 4. A later control reverses or changes that state. This is different from treating an overlay as a browser-only DOM trick. The source can establish that the current compiler understands the declarations; a target acceptance test must establish focus behavior, device presentation, dismissal behavior, and any caller/permission boundary. ## Test a flow as observations For an actual product flow, record each step as an observable fact: | Step | Record | | --- | --- | | Entry | target, runtime version, starting page/session state | | Trigger | exact node/event the reviewer invoked | | Intermediate result | visible tree/presentation and expected state change | | Exit | close/back/dismiss behavior and final state | | Boundary | any required caller identity, data scope, or target limitation | Do not say that a Showcase source file “has passed a flow test” unless that exact registered target, version, and sequence were run. For event authoring, see [Events, navigation, and visibility](../dsl-events-navigation-visibility/); for session updates, see [Sessions, patches, and scenes](../sessions-patches-scenes/). --- ## Example: local state and events URL: https://www.arcblock.io/en/docs/aup/example-local-state-events/ The current DSL Showcase registers a `set-sugar` page. Its source contains a compact authoring example: ```aup button rename "Rename" primary -> set headline props {content: "Renamed"} button load "Load" primary -> set list src "/modules/index" ``` The first action targets a named node’s props; the second changes a named node’s data source. Both compile into the AUP node/event contract described elsewhere in this board. ## What this example proves - The current DSL parser/compiler accepts these two `set` shorthand forms in Showcase source. - The named target makes the intended local update inspectable in source. - The file is registered in the current DSL Showcase app page map. ## What it does not prove - A remote deployment or any historical static Showcase page is live. - `/modules/index` is readable in every session, scope, or target. - Every renderer presents the same update or interaction. To turn this into a product claim, run the registered app locally in the target runtime, trigger each action, and record the target, URL, version, and observable result. Do not cite the source file alone as an end-to-end acceptance result. Read [Events, state, and bindings](../events-state-bindings/) for the contract and [Caller identity and safety](../caller-identity-safety/) for the permission boundary. --- ## Example: minimal app URL: https://www.arcblock.io/en/docs/aup/example-minimal-app/ `minimal-app` is the smallest currently documented **complete ARC app** recipe. It is deliberately more than a single AUP file: the recipe provides one Web page, one AUP app, one agent, and a settings-shell source/defaults. Its profile checks declared pages/capabilities and structural limits; it does not by itself prove that every capability has a live end-to-end instance configuration. ## Reproduce the example ```bash arc blocklet recipe explain minimal-app arc blocklet create ./hello-aup --recipe minimal-app --name hello-aup arc dsl format ./hello-aup --write arc dsl lint ./hello-aup arc dsl validate ./hello-aup arc blocklet check ./hello-aup --profile minimal-app arc blocklet run ./hello-aup ``` On ARC `2.0.0-beta.25`, creation reports 18 files and prints an absolute path for the next validation step. The local run prints both a `.localhost` URL and a universal query URL; use the first in Chrome/Firefox and the query URL where the subdomain form is not available. ## What was actually accepted The recipe was created in an isolated local directory, then formatted, linted, validated, and checked against `minimal-app`. In a direct local run, the root screen showed the app name, `App`, `Agent`, and `Settings`, plus the recipe’s “A tiny complete app.” description. That confirms the bounded local route, not an external deployment or every possible renderer/device interaction. The settings defaults are seeded into `/instance` at activation time. A new scaffold and a passing profile should therefore not be described as already carrying a live user-instance setting before that activation boundary exists. ## Extend it without losing the evidence 1. Keep the first run unchanged and record its browser result. 2. Make one source change at a time: a page, one interaction, or a declared data path. 3. Repeat the command chain and inspect the target that owns the claim. 4. Use `generate --check` only when validating compatibility artifacts; it is not required to make the source-first local app run. For the source/artifact distinction, read [Sources, artifacts, and JSON compatibility](../source-artifact-json-compatibility/). A minimal static content site is a separate target-specific Web Device path, not a variant of this complete-app recipe. --- ## Example: Web layout URL: https://www.arcblock.io/en/docs/aup/example-web-layout/ The Web Device first-site guide created a locally accepted layout: ```aup page index { hello main title="Hello, Web Device" text="This page is rendered by a local blocklet." } ``` `hello` is a site component under `.web/components/hello/`; its manifest, renderer, and stylesheet form the site presentation layer. In ARC `2.0.0-beta.25`, this layout was built and opened through a direct local blocklet run. ## What this is an example of - An AUP page layout composing a Web Device site component. - A static Web page with a declared route, site configuration, and local browser acceptance. - A useful separation between page structure and reusable HTML/CSS implementation. ## What it is not an example of - A claim that every native AUP primitive is valid as a Web layout section. - An interactive AUP session, patch sequence, or cross-device renderer proof. - A DID Space deployment. Use the direct static-tree renderer only for target-supported nodes, and use Web components for reusable layout sections. The full site file tree and commands belong to the target-specific Web Device documentation. For the two Web-facing AUP paths, see [AUP on Web Device](../on-web-device/). --- ## Examples and evidence URL: https://www.arcblock.io/en/docs/aup/examples/ This section distinguishes locally accepted paths from source-level examples. Every leaf identifies its source, registered entry, available verification record, and known limit. A Showcase’s physical file, static prose, or declared domain alone is not evidence of a publicly runnable example. ## Choose evidence deliberately 1. [Live example contract](../live-example-contract/) establishes the read-only document pattern and its first document-target render. 2. [Minimal app](../example-minimal-app/) is the current locally run recipe path. 3. [Local state and events](../example-local-state-events/) is a registered source example; its target acceptance remains a separate check. 4. [AFS data binding](../example-afs-data-binding/) and [interaction flow](../example-interaction-flow/) are source examples with their stated runtime boundaries. 5. [Web layout](../example-web-layout/) explains the source-to-Web distinction without claiming a general native-layout recipe. --- ## Build a first AUP app URL: https://www.arcblock.io/en/docs/aup/first-app/ This path uses `minimal-app` because the current CLI explicitly provides it and can explain its sources, generated artifacts, and checks. It creates a complete slice rather than pretending to be a pure-AUP app. ## Inspect the recipe boundary first ```bash arc blocklet recipe explain minimal-app ``` On `2.0.0-beta.25`, the output identifies `web`, `aup`, `agent`, and `settings` capabilities, and lists source DSL, AFS data, compatible artifacts, and the profile check. ## Create the app ```bash arc blocklet create ./hello-aup --recipe minimal-app --name hello-aup ``` In this page's verification, the CLI confirmed 18 created files and printed a next validation command using the **resolved absolute path** of the created directory. That absolute path depends on where you create the project, so do not treat it as tutorial syntax. ```text Created minimal app blocklet "hello-aup" with 18 file(s). ``` After creation, read these sources instead of editing generated artifacts: | File | Role | |---|---| | `.aup/app.aup` | DSL source for the AUP app | | `pages/index/layout.aup` | DSL source for the Web page layout | | `.web/components/app-hero/component.dsl` | DSL source for the site-component manifest | | `agents/app-agent/agent.dsl` | DSL source for the agent manifest | | `seed/settings/.../settings.aup` | Settings source | The recipe also writes some JSON compatibility artifacts, but it does not materialize `.aup/app.json`, `.aup/pages/*.json`, or `.aup/wrapper.json` in advance. If a consumer explicitly needs them, read [Generate, lint, and migrate](../dsl-generate-lint-migrate/); do not hand-edit them when no consumer needs them. Continue to [Validate, run, and inspect](../validate-run-inspect/). --- ## Frames, bridges, and embedded surfaces URL: https://www.arcblock.io/en/docs/aup/frames-bridges-embedded-surfaces/ Embedding crosses a trust boundary. It needs a narrower claim than “the page can show another page.” ## Frame and bridge in an interactive AUP Web session This section describes the interactive AUP Web-session renderer. In that renderer, use `frame` for an isolated document context or controlled embed. A capability bridge at `window.aup` is available only when the frame is explicitly bridge-enabled, trusted, and same-origin. Third-party embeds should remain isolated by default; a bridge is not a general cross-origin SDK. The Web Device document target is a different path. Its static `frame` output and Markdown content embeds do not establish a `window.aup` bridge, parent session, or general data/action access. Treat an embedded document frame as third-party content unless a separate interactive-session contract says otherwise. Before enabling one, make the following decisions visible in review: 1. Which exact origin is trusted? 2. Which data path and actions are available to the embed? 3. How are session lifetime, parent/child messages, and failure handled? 4. What browser/device target actually passed the intended interaction? ## Surface in an interactive AUP Web session In the interactive AUP Web-session renderer, `surface` can render an AFS path or connect to a remote AUP endpoint. Nested-session behavior still depends on the runtime and connection context. Do not promise that any remote endpoint, cross-origin transport, or nested event flow will work merely because the `surface` node parses. `terminal` is a distinct WebSocket terminal widget, not the AUP protocol itself. It therefore carries its own endpoint, authorization, and lifecycle review rather than inheriting a blanket AUP trust claim. The first documentation edition has one direct document-target input example, but it does not use a frame, bridge, or surface. A full runtime demo still needs its own origin, least-privilege data scope, and browser acceptance before it belongs in a reference page. --- ## Get started URL: https://www.arcblock.io/en/docs/aup/getting-started/ This section uses the current `minimal-app` recipe as its boundary. First separate AUP, DSL, and renderer responsibilities; then create the smallest complete app containing Web, AUP, an agent, and settings, and inspect it directly on your machine. ## Read in this order 1. [Product layers and scope](../product-layers/) to decide whether the task is AUP, DSL, a renderer, or a Web Device site. 2. [Build a first AUP app](../first-app/) to create the verified beta.25 `minimal-app` boundary. 3. [Validate, run, and inspect](../validate-run-inspect/) to distinguish source checks from the direct local acceptance URL. --- ## Live examples: scope and contract URL: https://www.arcblock.io/en/docs/aup/live-example-contract/ A reference page can place source and actual renderer output next to each other. The page itself remains read-only. A live example may expose only the interaction the represented node already owns. It never becomes an editor for the source, manifest, or documentation. Do not treat every rendered object as the same kind of component. Markdown directives become an AUP tree for the document target; native AUP primitives have their own target-specific support; and a Web Device `.web` component belongs in a page layout, not in a generic Markdown directive. This page proves only the document-target Markdown → AUP path. ## Sample contract | Field | Value | | --- | --- | | Purpose | Unbound document-target `input`, plus `view` mode `tabs` as static UI chrome | | Boundaries | No `bind`, session patch, AFS write, `exec`, multi-field form, or layout-component API | | Author entry | Content Markdown directives (`::input`, `::::view`) | | Surface | Web Device **document** target (static prerender + browser form controls) | | Public status | `released` for these two nodes on document | | Fallback / failure | Missing `id` → unstable DOM id collision risk; unknown tab children still render as panels without switching JS requirements beyond radio/CSS | | Verification | `arc --version` = `2.0.0-beta.28`; routes below; narrow viewport still shows controls | For every published example, record in the same place: the source that produces the node; the data or manifest boundary; the target that renders it; and the exact behavior the reader should observe, including what is deliberately absent. ## A document-target text input This example is an unbound AUP `input` node. It has no `bind`, event, action, source path, or write capability. Type in it if useful. The field changes only as a browser form control; no document, manifest, AFS record, or session setting is changed. A browser may restore a form value when it reloads a page, which is browser behavior rather than AUP persistence. Give every field an explicit `id`. The content reader promotes that attribute to the node’s top-level `id` (arc#3321). Without it, multiple inputs on one page can share a broken DOM id. Source: ```markdown ::input{id="docs-live-name" type="text" label="Name" placeholder="Type only in this example" value="Ada"} ``` Rendered: ::input{id="docs-live-name" type="text" label="Name" placeholder="Type only in this example" value="Ada"} The same Web Device document renderer that reads this page renders the field. This is a real document-target result, but it is not evidence of a bound form, an AUP session patch, or persistence. Use it only as evidence for one unbound field, not as a copyable multi-field live form pattern. ### Failure and limits | Situation | Expected result | | --- | --- | | No `id` on `::input` | Field still renders; DOM id is unstable across fields on the same page | | `bind` / session fields in Markdown here | Not part of this contract; do not invent them on a docs page | | Narrow viewport | Label, control, and placeholder remain readable; no second layout mode is required | ## A document-target `view` with mode `tabs` `view` is a released cross-device primitive. On the document target, `mode="tabs"` is static UI: radio inputs and panels, not a separate widget session. Author tabs with a generic container directive so nested panel bodies survive (arc#2598). Source: `````markdown ::::view{id="docs-live-tabs" mode="tabs" label="Package manager"} :::view{label="pnpm"} Install with `pnpm install`. ::: :::view{label="npm"} Install with `npm install`. ::: :::: ````` Rendered: ::::view{id="docs-live-tabs" mode="tabs" label="Package manager"} :::view{label="pnpm"} Install with `pnpm install`. ::: :::view{label="npm"} Install with `npm install`. ::: :::: Switching tabs only changes which panel is visible in the browser. It does not write content, open an AUP session, or run shell commands. The outer fence needs more colons than nested containers, same as other container directives. ### Failure and limits | Situation | Expected result | | --- | --- | | Leaf `::view` with no body | Empty panel / no body content | | Outer fence with too few colons | Parser misreads structure; panels may drop | | No `label` on the tabs container | Tabs still render; accessible name on the tablist is omitted | | Treating tabs as layout `.web` components | Wrong surface — layout components use `layout.aup`, not this directive | ## What a list must add An `afs-list` reference needs a separate contract. Its source must name the list layout and template; its data section must name a read-only fixture or a declared AFS path; and the page must identify the renderer/session that actually resolved it. A static document target can render literal child nodes, but it does not by itself prove that a source-backed list can read an arbitrary path. The current Showcase `list-basic` source is useful evidence for that next slice: it binds `afs-list` to packaged `data/items` and has no write action on the list itself. Before it becomes an embedded runtime sample, use a dedicated minimal demo origin rather than the full Showcase, keep its fixture data read-only, and verify that the frame has no bridge, write, or `exec` path. This page does **not** claim a verified live `afs-list` sample. ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `input`, `view`, `::input` | | Implementation | `providers/runtime/web-device/src/content-reader.ts` (directive → AUP, id promotion); `renderer/primitives/input.ts`; `renderer/primitives/view.ts` (tabs) | | Tests | `content-reader.test.ts` (id promotion, nested tabs); `renderer/primitives.test.ts` (tabs ARIA / radio) | | Public routes | `/en/docs/aup/live-example-contract/` · `/zh/docs/aup/live-example-contract/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` then open those routes (desktop + ~390px width) | | Accept | Source fence matches rendered control; typing stays local; tab switch does not network-write | For the isolation boundary, read [Frames, bridges, and embedded surfaces](../frames-bridges-embedded-surfaces/). For static Web Device versus an interactive AUP session, read [AUP on Web Device](../on-web-device/). --- ## Nodes, events, and messages URL: https://www.arcblock.io/en/docs/aup/node-event-message-reference/ This reference describes the AUP tree contract that an author can intentionally write against. It does not make every internal session message a long-term authoring API. ## Node fields An AUP node has a required `id` and `type`. The current public node shape also has these optional fields: | Field | Authoring role | Boundary | | --- | --- | --- | | `props` | Static presentation/input properties | Its valid keys depend on `type` | | `src` | A read-oriented data source | It does not itself grant write access | | `bind` | A normal read/write binding for a supported input flow | The receiving node and target still decide what they support | | `propBind` | Server-managed binding for a dotted property path to an AFS path | Use only where the owning component declares it | | `state` | Application state supplied with the node | Do not treat renderer-local transient UI as universally persistent state | | `events` | Named interactions and their actions | The event name is defined by the node/renderer contract | | `children` | Nested semantic nodes | A type may constrain its child shape | | `testId` | Stable test-oriented identifier | It is not reader-facing copy or routing identity | `type` names a semantic capability, not a particular HTML tag or native widget. See [Primitive taxonomy and evidence](../primitive-support-matrix/) before documenting a capability as cross-device. ## Events and navigation For current DSL authoring, `->` is the click shorthand for `button` and `action`. Other nodes use an explicit `on ->` form. A page change uses the canonical root-state update: ```text button open "Open" primary -> page details ``` which compiles to a target of `"_root"` with `set.page`. The earlier top-level `page:` shape is a compatibility form, not the preferred contract for new source. ## Messages: use the right level of abstraction Interactive delivery begins with a rendered tree and may subsequently use tree-versioned patches. Those messages let a session keep a target surface synchronized; authors normally express them through nodes, state, and events rather than constructing patch transport by hand. A static Web Device page can render a supported tree without opening that interactive session. Read [Events, state, and bindings](../events-state-bindings/) for task-oriented examples and [Patches, scenes, and capabilities](../patches-scenes-capabilities-reference/) for the update boundary. --- ## AUP on Web Device URL: https://www.arcblock.io/en/docs/aup/on-web-device/ Web Device is a Web-facing site provider, not a layer that collapses every AUP and website concept together. It has two currently verifiable AUP paths: a supported AUP tree can render directly to static HTML, and a page-layout AUP can compose site components for reusable Web presentation. These are related paths, not permission to place arbitrary native primitives directly into a Web layout section. | Concern | AUP | Web Device | | --- | --- | --- | | Tree, event, state, capability/degradation | Defines the semantic contract | Uses the target renderer's support boundary | | Static HTML | Can produce it from a supported tree | Owns the Web renderer, page assembly, and build | | Page directories, content objects, locales, SEO, and themes | Does not define them | Organizes them through `pages/`, `content/`, and `.web/` | | Site components | Can be referenced by a layout | Live in `.web/components/` as reusable Web implementation | ## Choose the right path When arranging branded components, content lists, or themed styles in a site page, start with Web Device's `pages/` and `.web/components/`, then use an AUP layout for structure. When verifying a cross-device interactive tree, session patch, or device capability, start with an AUP app and its target renderer. The paths share AUP semantics but require different acceptance: - AUP-app browser acceptance observes session, navigation, event, and patch behavior. - Web Device acceptance observes static pages, locales, links, SEO, and build output. - One green path does not replace the other. Static HTML success is not interactive-session success; an AUP app running is not proof that a content site has correct routes and SEO. ## A minimal order for a site author 1. In Web Device, create `.route/web`, `.web/site.yaml`, and `pages/index/` first. 2. Use Web components for reusable layout sections. Treat direct native-tree static rendering as its own supported-renderer path, not as a replacement for the layout component contract. 3. Use AUP's event/state contract for interaction and Web Device's source/binding contract for content objects. 4. Run DSL/site checks, build, and real browser acceptance separately. Do not treat hidden UI, static rendering, or a page component as AFS authorization. Caller identity and scope remain a separate boundary. Site-building steps belong to the target-specific Web Device layer, not to this AUP board. ## Related evidence For a live document-surface walk of the 18 primitives, Markdown directives, and deck media host (gallery / YouTube media-fill / tweet clamp) on this site: [AUP capability tour](/en/docs/aup/capability-tour-slides/). The tour is evidence for the document target only; it does not replace device capability reports or Web Device site acceptance. --- ## AUP URL: https://www.arcblock.io/en/docs/aup/overview/ AUP is ARC’s declarative UI model. An application describes a semantic interface tree, data, and interaction first. Interactive AUP is normally presented by an ARC session and target renderer; Web Device can also render a supported AUP tree directly to static HTML. Keep three layers distinct: | Layer | Owns | Does not own | |---|---|---| | AUP | The semantic node/event/state/data contract and shared degradation rules | The HTML or native-control implementation for one device | | AUP DSL | The readable, source-first authoring form and generation tools | A second UI model | | Device and renderer | Reporting actual `DeviceCaps` during handshake and implementing presentation and target-side degradation from them | The application’s business intent | For AUP app configuration, the current loader prefers `.aup/app.aup`. Only when it is absent does it load `.aup/app.json` as JSON source; a present but invalid DSL source fails instead of silently falling back. JSON-first apps remain supported, while DSL-first apps can expose or materialize compatible JSON on demand. These are different input/artifact roles for one AUP model, not two products. ## Start from the task | If you need to | Start here | |---|---| | Create and run a first complete AUP app | [Get started](../getting-started/) | | Understand trees, events, sessions, and capabilities | [Core concepts](../concepts/) | | Author and maintain source with DSL | [Author with DSL](../author-with-dsl/) | | Understand how ARC runs it on device surfaces | [Run in ARC](../run-in-arc/) | | Inspect source examples and their evidence boundaries | [Examples and evidence](../examples/) | | Look up an exact, versioned contract | [Reference](../reference/) | ## Relationship to Web Device Web Device is a Web-facing AUP target: it can statically render supported AUP trees to HTML and lets site pages use AUP to compose Web components. It is not a replacement for an interactive AUP session; a site also has its own `.web/` components, pages, themes, content, and routing conventions. Components are one layer for richer HTML, CSS, and interaction on the Web, not the only valid form of an AUP tree. Site directories, content objects, and themes belong to the Web Device layer and are intentionally outside this AUP board. For AUP semantics, DSL, sessions, or degradation, remain in this board. ## Evidence and versions This board does not treat stale Showcase counts or an unregistered Showcase page file as evidence of a current deployed demo. Implementation semantics are grounded in current source and tests. Its command-bearing pages were run with `arc` `2.0.0-beta.25`; a page that has been filled in identifies its source, test, and runtime boundary. The non-rendered board ledger preserves archaeology and human decisions. --- ## Patches, scenes, and capabilities URL: https://www.arcblock.io/en/docs/aup/patches-scenes-capabilities-reference/ This reference separates three related but different concerns: keeping an interactive tree current, selecting a presentation for a target, and describing a device-level scene. ## Render first; patch a known tree An interactive session starts from a rendered AUP tree. Later changes can be sent as patches against a tree version. The current patch vocabulary includes `create`, `update`, `remove`, and `reorder` operations. That is a renderer/session synchronization mechanism, not a request for application authors to edit arbitrary transport messages. When a state change is simple, express it as state/event intent in DSL or AUP source. Let the runtime determine the resulting tree update. A target that misses or rejects an update must not be assumed to have applied the author's intended state merely because a source file validated. ## Capabilities are reported by the target The AUP model contains shared degradation rules; the actual device capability set (`DeviceCaps`) is reported during handshake and the renderer applies target presentation. Current primitive support values are: ```text native | webview | partial | unsupported ``` Those values describe a target’s relation to a primitive, not a universal quality score for the whole app. The current shared degradation contract is deliberately small. The canonical list of its nine chains is in [Device capabilities and degradation](../device-capabilities-degradation/); keep that target-specific acceptance guidance next to the chain list rather than copying it into every reference page. A custom or unknown type without a chain passes through unchanged; it is not automatically converted to text. This is why a cross-device claim requires a concrete primitive and target check. ## Scene is not a generic UI escape hatch The runtime has scene-oriented delivery surfaces, but their lower-level transport details are not a stable shortcut around node/event/state authoring. Use a scene only when the relevant target contract and acceptance test are known. Do not use a frame, bridge, or embedded surface to bypass capability or data-scope review. For the current primitive inventory, see [Primitive taxonomy and evidence](../primitive-support-matrix/). For safe authoring of state changes, see [Events, state, and bindings](../events-state-bindings/). --- ## Primitive taxonomy and evidence URL: https://www.arcblock.io/en/docs/aup/primitive-support-matrix/ “The parser accepts a type” and “the type works on this device” are different statements. This reference first gives the current type taxonomy, then leaves the final support decision to actual `DeviceCaps`, the target renderer, and local acceptance. ## The 18 cross-device primitives | Group | Current types | | --- | --- | | Basic interface | [`view`](../primitives/view/), [`text`](../primitives/text/), [`media`](../primitives/media/), [`input`](../primitives/input/), [`action`](../primitives/action/), [`overlay`](../primitives/overlay/) | | Structure and time | [`table`](../primitives/table/), [`time`](../primitives/time/), [`chart`](../primitives/chart/), [`map`](../primitives/map/), [`calendar`](../primitives/calendar/) | | Interactive surface | [`chat`](../primitives/chat/), [`rtc`](../primitives/rtc/), [`explorer`](../primitives/explorer/), [`editor`](../primitives/editor/), [`canvas`](../primitives/canvas/), [`surface`](../primitives/surface/), [`afs-list`](../primitives/afs-list/) | Those 18 names form the cross-device primitive table and are the subject of the capability map. Open [AUP primitives](../primitives/) for one contract page per name. For each type, a device reports `native`, `webview`, `partial`, or `unsupported`; do not substitute the table for a real target report. ## The 42 Web-only widgets The current type table also contains 42 Web widgets. They include presentation/site-oriented types such as `frame`, `terminal`, `breadcrumb`, `pagination`, `tooltip`, `comments-surface`, `blocklet-embed`, `webgl-hero`, and `wm-surface`. They can have a renderer in the Web runtime, but they are not cross-device primitives and do not enter the guaranteed `DeviceCaps.primitives` scope. To avoid writing “60 types” as “60 cross-device capabilities,” use these rules for documentation and examples: | Claim | Required evidence | | --- | --- | | A primitive works on one target | That target's capability report plus real presentation acceptance | | A primitive has a fallback | A currently listed degradation chain, verified on the target | | A Web widget works | Web runtime/browser acceptance | | A custom type works | Target registration/renderer plus real acceptance | When an unknown/custom type has no shared chain, the current degradation implementation passes it through unchanged rather than automatically turning it into safe text. Before taking a custom type to a second renderer, design both its presentation and failure boundary. ## Nearby references - For device reports, the nine explicit degradation chains, and their failure shape: [Device capabilities and degradation](/en/docs/aup/device-capabilities-degradation/). - For node, props, data binding, and children semantics: [Semantic tree](/en/docs/aup/semantic-tree/). - For static HTML boundaries in Web Device: [AUP on Web Device](/en/docs/aup/on-web-device/). - For a document-surface walk of the 18 primitives, Markdown host, and deck media demos: [AUP capability tour](/en/docs/aup/capability-tour-slides/). This page is the `2.0.0-beta.25` type taxonomy, not a cross-version, cross-device compatibility promise. --- ## AUP primitives URL: https://www.arcblock.io/en/docs/aup/primitives/ These pages document the **18 AUP cross-device primitives** from `AUP_PRIMITIVES`. Each name has its own page. They are not Web Device layout components and not the 42 Web-only widgets. | Rule | Meaning | | --- | --- | | One page per primitive | Capability and sample boundary stay scoped to a single type | | Document vs full-web | Document capability comes from `DEVICE_CAPS_DOCUMENT`, not from Showcase success | | Sample honesty | Docs-safe samples show source + real render; unsupported types say so | | Not widgets | `frame`, `terminal`, `breadcrumb`, … belong to the Web-only widget set | ## Basic interface | Primitive | Document (current) | Page | | --- | --- | --- | | `view` | native | [view](./view/) | | `text` | native | [text](./text/) | | `media` | native | [media](./media/) | | `input` | native | [input](./input/) | | `action` | native | [action](./action/) | | `overlay` | unsupported | [overlay](./overlay/) | ## Structure and time | Primitive | Document (current) | Page | | --- | --- | --- | | `table` | native | [table](./table/) | | `time` | partial | [time](./time/) | | `chart` | unsupported (no live chart) | [chart](./chart/) | | `map` | unsupported | [map](./map/) | | `calendar` | unsupported | [calendar](./calendar/) | ## Interactive surface | Primitive | Document (current) | Page | | --- | --- | --- | | `chat` | unsupported | [chat](./chat/) | | `rtc` | unsupported | [rtc](./rtc/) | | `explorer` | unsupported | [explorer](./explorer/) | | `editor` | native (no writable IDE promise) | [editor](./editor/) | | `canvas` | unsupported | [canvas](./canvas/) | | `surface` | unsupported | [surface](./surface/) | | `afs-list` | native renderer; data contract open | [afs-list](./afs-list/) | ## Read next - [Primitive taxonomy and evidence](../primitive-support-matrix/) — 18 vs 42 widgets - [Device capabilities and degradation](../device-capabilities-degradation/) — chains and chart boundary - [Custom primitives and Web widgets](../custom-primitives-web-widgets/) — portability vs Web-only - [Live examples: scope and contract](../live-example-contract/) — what a docs sample may claim --- ## `action` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/action/ `action` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `action` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `released` | | Document capability | `native` | | Shared degradation chain | None (document reports native) | | Author entry | AUP tree · Markdown `::action` (often inside action-card) · DSL | | Document renderer / notes | `renderer/primitives/action.ts` (`safeHref`); cards synthesize action nodes | | Showcase evidence | form / portal pages; document cards path on markdown unit pages | ## When to use You need a labeled operation: navigation `href`, or (on interactive targets) `events.click` / `exec`. ## When not to use On public docs, use navigation-only actions. Do not promise AFS `exec` or destructive confirmations from a static document sample. ## Sample contract | Field | Value | | --- | --- | | Purpose | Navigation-only action on document | | Boundaries | No `exec`, no AFS write, no session | | Author entry | `::action{…}` | | Surface | Web Device **document** | | Public status | `released` | | Fallback / failure | Unsafe `href` schemes rejected; missing `href` → non-link span/button chrome | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (navigation action) This example places an ordinary navigation `href` with no event, `exec`, or data write. Source: ```markdown ::action{label="Open live example contract" href="/en/docs/aup/live-example-contract/" variant="primary"} ``` Rendered: ::action{label="Open live example contract" href="/en/docs/aup/live-example-contract/" variant="primary"} ### Non-link label (no href) Source: ```markdown ::action{label="Label only — not a navigation target" variant="secondary"} ``` Rendered: ::action{label="Label only — not a navigation target" variant="secondary"} Card composition: [action-card](/en/docs/web-device/markdown/action-card/). ### Failure and limits | Situation | Expected result | | --- | --- | | `javascript:` / `data:` href | Rejected by `safeHref`; not a clickable privileged link | | Missing `href` | Non-link presentation (`span` / button path without navigation) | | Expecting `exec` or AFS write | Out of contract on static document samples | | Nested inside action-card | Still navigation-only unless a separate interactive runtime is proven | ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `action` | | Implementation | `content-reader.ts` (generic `::action`); `renderer/primitives/action.ts` (`safeHref`) | | Public routes | `/en/docs/aup/primitives/action/` · `/zh/docs/aup/primitives/action/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · click navigation action → ordinary navigation only | | Accept | Primary action navigates; label-only action is not a privileged write; no `exec` | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `afs-list` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/afs-list/ `afs-list` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `afs-list` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `experimental` | | Document capability | `native` (renderer present; **data contract open**) | | Shared degradation chain | None | | Author entry | AUP + source/fixture (`layout`, `itemStyle`, `from` / `src`) · container directive with static children | | Document renderer / notes | `renderer/primitives/afs-list.ts` (static children; empty+src → “Loading…”; empty no src → “No items”) | | Showcase evidence | `list-basic.aup` and related list-* pages (`from "data/items"`) | ## When to use Declarative lists over AFS paths or packaged fixtures on interactive targets. ## When not to use Do not bind arbitrary AFS paths in public docs. Do not claim verified live list sampling without a read-only fixture origin. ## Sample contract | Field | Value | | --- | --- | | Purpose | Honest empty-state and static-children rendering on document | | Boundaries | No write actions; no arbitrary AFS path; no frame bridge; **not** proof that a path resolves on this site | | Author entry | Container directive `:::afs-list{…}` | | Surface | Web Device **document** | | Public status | `experimental` | | Fallback / failure | No children + no src → “No items”; no children + src → “Loading…” (static) | | Verification | Routes below · empty states only; path-backed live data still open | ## Document sample (empty — no items) Source: ```markdown :::afs-list{id="docs-prim-afs-list-empty" layout="list" itemStyle="row"} ::: ``` Rendered: :::afs-list{id="docs-prim-afs-list-empty" layout="list" itemStyle="row"} ::: ## Document sample (src without children — loading chrome) This shows the static renderer’s loading empty state. It does **not** fetch an AFS path on this documentation site. Source: ```markdown :::afs-list{id="docs-prim-afs-list-loading" layout="list" itemStyle="row" src="data/items"} ::: ``` Rendered: :::afs-list{id="docs-prim-afs-list-loading" layout="list" itemStyle="row" src="data/items"} ::: ## Document sample (static children) Pre-populated children render as list items. This is not evidence of AFS `list()` resolution. Source: ````markdown :::afs-list{id="docs-prim-afs-list-static" layout="list" itemStyle="row"} Static row one — authored as document children, not fetched. Static row two — still not an AFS path proof. ::: ```` Rendered: :::afs-list{id="docs-prim-afs-list-static" layout="list" itemStyle="row"} Static row one — authored as document children, not fetched. Static row two — still not an AFS path proof. ::: Showcase `list-basic` binds `afs-list` to packaged `data/items` with no write action on the list itself — useful evidence for a future embedded sample with a dedicated read-only fixture origin. See [Live examples: scope and contract](../../live-example-contract/) (“What a list must add”). ### Failure and limits | Situation | Expected result | | --- | --- | | Empty list, no `src` | “No items” empty chrome | | Empty list with `src` | “Loading…” static chrome (no fetch proof here) | | Arbitrary AFS path on public docs | Out of contract | | Expecting write / drop / mutate | Out of contract | ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `afs-list` | | Implementation | `renderer/primitives/afs-list.ts`; caps `device-caps.ts` | | Public routes | `/en/docs/aup/primitives/afs-list/` · `/zh/docs/aup/primitives/afs-list/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · confirm empty / loading / static-children chrome | | Accept | Empty states match; page states data contract open; no arbitrary path claim | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `calendar` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/calendar/ `calendar` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `calendar` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | calendar → table → text | | Author entry | AUP/DSL on supporting interactive targets | | Document renderer / notes | No document native calendar renderer; chain applies | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/calendar.aup` | ## When to use Month/week/day calendar composition with events on a capable target. ## When not to use Do not assume a degraded table preserves calendar semantics. No document live sample. ## Document sample **Not provided.** Document capability is `unsupported`. Shared chain: `calendar` → `table` → `text`. The fallback table is not a calendar product surface. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `canvas` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/canvas/ `canvas` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `canvas` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | canvas → media → text | | Author entry | AUP on interactive/visual targets | | Document renderer / notes | No document native canvas path; chain applies | | Showcase evidence | Interactive runtime / visual demos (not document sample) | ## When to use Freeform drawing or pixel surfaces on capable devices. ## When not to use Do not ship canvas demos as static docs capability. ## Document sample **Not provided.** Document capability is `unsupported`. Shared chain: `canvas` → `media` → `text`. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `chart` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/chart/ `chart` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `chart` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `experimental` | | Document capability | `unsupported` | | Shared degradation chain | chart → table → text (document yields a table, not Chart.js) | | Author entry | AUP/DSL on interactive Web · **no** `::chart` Markdown directive | | Document renderer / notes | Full-web Chart.js path; document: degrade + optional static reshape to table (arc#3458) | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/chart.aup` | ## When to use Full interactive Web surface with chart capability and Chart.js presentation. ## When not to use Do not publish a live chart as a document capability. Do not invent `::chart` in site content. ## Document sample **No live chart sample.** Facts on the static document target: | Fact | Current boundary | | --- | --- | | Document capability | `DEVICE_CAPS_DOCUMENT` does **not** list `chart` → `unsupported` | | Shared chain | `chart` → `table` → `text` | | What you get | A **table**, not a Chart.js graphic; no CDN chart load on this path | | Data reshape | When the runtime includes static reshape (arc#3458), inline `labels`/`datasets` become table columns/rows instead of an empty “No data” table | | Markdown | **No** defined `::chart` directive | | Docs policy | Prefer an author-written Markdown or AUP `table` when the page needs data | Showcase `chart` is evidence for the **interactive** surface only. Upstream issue closed ≠ docs-safe live chart (see [Device capabilities and degradation](../../device-capabilities-degradation/) and internal capability-matrix §0.5–0.6). ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Deck path exception (not a general MD chart dialect) On **document articles**, chart stays on the degradation chain (table/text). There is still **no** product-wide `::chart` Markdown dialect for arbitrary docs. On a **`slides: true` deck**, the runtime may use `DEVICE_CAPS_DECK` (arc#4005 / #4011) so chart stays a progressive-enhance shell. Markdown array props arrive as strings and need coercion (arc#4013). Capability-tour demos are **deck-scoped evidence**, not a rewrite of this unit contract for every page. ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `chat` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/chat/ `chat` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `chat` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | No shared document degradation chain | | Author entry | AUP session · web-chat / web-full caps (`DEVICE_CAPS_WEB_CHAT`) | | Document renderer / notes | Interactive renderers; not document-native | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/chat.aup` (often composed with `afs-list`) | ## When to use Messaging surfaces that require session identity, channel lists, and message streams. ## When not to use Do not paste a chat shell into static docs. Identity and permission prerequisites apply. ## Document sample **Not provided.** Document reports `unsupported` for `chat`. There is no document degradation chain that invents a safe chat UI. Use Showcase `chat` and a real session for acceptance. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `editor` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/editor/ `editor` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `editor` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `experimental` | | Document capability | `native` (renderer present; public sample is local-only) | | Shared degradation chain | editor → input → text (when unsupported) | | Author entry | AUP tree / DSL · generic Markdown `::editor{…}` | | Document renderer / notes | `renderer/primitives/editor.ts` (textarea; `readOnly` only when boolean `true` in AUP props) | | Showcase evidence | Composition pages using editor nodes | ## When to use Code or long-form edit surfaces on targets that implement editor. ## When not to use Do not claim collaborative editing, LSP, multiplayer, or write-back from a docs page. ## Sample contract | Field | Value | | --- | --- | | Purpose | Honest document-target editor control (local textarea only) | | Boundaries | No LSP, no multiplayer, no AFS write, no IDE product promise | | Author entry | `::editor{…}` generic directive | | Surface | Web Device **document** | | Public status | `experimental` | | Fallback / failure | When unsupported: chain to input → text; empty value → empty textarea | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (local textarea) Document registers an `editor` renderer. The sample below is an unbound control: typing changes only the browser textarea. Markdown attributes are strings — do not assume `readOnly=true` from MD attributes sets boolean `true` the way AUP JSON does. Prefer AUP JSON/DSL when you need a strict read-only prop. Source: ```markdown ::editor{id="docs-prim-editor" language="json" label="Example snippet" value="{ \"ok\": true }"} ``` Rendered: ::editor{id="docs-prim-editor" language="json" label="Example snippet" value="{ \"ok\": true }"} AUP JSON shape (interactive / when you need boolean `readOnly`): ```json { "id": "snippet", "type": "editor", "props": { "label": "Example", "language": "json", "readOnly": true, "value": "{ \"ok\": true }\n" } } ``` ### Failure and limits | Situation | Expected result | | --- | --- | | Typing in the document sample | Local browser state only; no document/AFS write | | Expecting LSP / multiplayer | Out of contract | | Unsupported target | Degrades via editor → input → text | | MD `readOnly="true"` string | Not guaranteed to equal AUP boolean `true` | ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `editor` | | Implementation | `renderer/primitives/editor.ts`; caps `device-caps.ts`; chain `degradation.ts` | | Public routes | `/en/docs/aup/primitives/editor/` · `/zh/docs/aup/primitives/editor/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · open routes; type stays local | | Accept | Textarea renders with seed value; no network write; experimental status visible | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `explorer` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/explorer/ `explorer` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `explorer` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | No shared chain (pass-through / unknown handling) | | Author entry | AUP composition (often `afs-list` + widgets) on interactive targets | | Document renderer / notes | Document RENDERERS: none for explorer; Showcase composes primitives/widgets | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/explorer.aup` | ## When to use IDE-style directory browser compositions with declarative select/navigate retargeting. ## When not to use Do not treat explorer as a single layout component. Document has no native explorer renderer. ## Document sample **Not provided.** Document capability is `unsupported`. Explorer demos are multi-node compositions (see Showcase `explorer`) and require interactive data paths. Read [afs-list](../afs-list/) for the list half of that composition — still without a closed live data contract on this site. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `input` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/input/ `input` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `input` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `released` | | Document capability | `native` | | Shared degradation chain | None (document reports native) | | Author entry | AUP tree · Markdown `::input{…}` (generic directive → type) | | Document renderer / notes | `renderer/primitives/input.ts`; content-reader id promotion (arc#3321) | | Showcase evidence | form-* Showcase pages; document path verified on live-example-contract | ## When to use You need a form control (text, select, checkbox, …) as a semantic node. ## When not to use Do not put `bind`, multi-field forms, or session writes on a public docs page. Give every field an explicit `id`. ## Sample contract | Field | Value | | --- | --- | | Purpose | Unbound document-target input | | Boundaries | No `bind`, session patch, AFS write, `exec`, or multi-field form product | | Author entry | `::input{…}` | | Surface | Web Device **document** | | Public status | `released` | | Fallback / failure | Missing `id` → unstable DOM id across fields; unknown type may degrade presentation | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (unbound text input) This field is an unbound AUP `input`. Typing changes only the browser form control. No document, manifest, AFS record, or session setting is written. Source: ```markdown ::input{id="docs-prim-input-name" type="text" label="Name" placeholder="Type only in this example" value="Ada"} ``` Rendered: ::input{id="docs-prim-input-name" type="text" label="Name" placeholder="Type only in this example" value="Ada"} ### Additional control (checkbox) Source: ```markdown ::input{id="docs-prim-input-ack" type="checkbox" label="I understand this stays local"} ``` Rendered: ::input{id="docs-prim-input-ack" type="checkbox" label="I understand this stays local"} Full shared contract: [Live examples: scope and contract](../../live-example-contract/). ### Failure and limits | Situation | Expected result | | --- | --- | | No `id` on `::input` | Field still renders; DOM id is unstable across fields on the same page | | `bind` / session fields in Markdown here | Not part of this contract; do not invent them on a docs page | | Multi-field live form with submit | Out of contract for public docs | | Narrow viewport | Label, control, and placeholder remain readable | ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `input` · `::input` | | Implementation | `content-reader.ts` (id promotion); `renderer/primitives/input.ts` | | Public routes | `/en/docs/aup/primitives/input/` · `/zh/docs/aup/primitives/input/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · type in the field; reload may restore browser form state only | | Accept | Source matches control; typing stays local; no network write on change | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `map` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/map/ `map` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `map` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | map → media → text | | Author entry | AUP/DSL on full-web (Leaflet / MapLibre in Showcase) | | Document renderer / notes | No document native map renderer; chain applies | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/map.aup` | ## When to use Interactive map/globe UI on a target that reports map support. ## When not to use Do not embed live maps in static docs. Tile CDN and JS map stacks are not document capabilities. ## Document sample **Not provided.** Document capability is `unsupported`. Shared chain: `map` → `media` → `text`. Accept maps on Showcase `map` (full-web), not as a docs live sample. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) ## Deck path exception Ordinary **document** pages do not embed a live map. A **`slides: true` deck** may keep a map progressive-enhance shell under `DEVICE_CAPS_DECK` (arc#4005 / #4011 + #4013). Tour demos are deck-scoped evidence only. --- ## `media` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/media/ `media` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `media` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `released` | | Document capability | `native` | | Shared degradation chain | None (document reports native) | | Author entry | AUP tree · generic Markdown directive `::media{…}` · Markdown images (separate img path) | | Document renderer / notes | `renderer/primitives/media.ts` | | Showcase evidence | Markdown image path; Showcase media-heavy pages | ## When to use You need a semantic media node with type (`image` / `video` / `audio` / `avatar`) and optional caption. ## When not to use Do not treat unrestricted third-party embeds as trusted media. Same-site / whitelist rules for frames are separate ([embed](/en/docs/web-device/markdown/embed/)). Inline Markdown `![alt](src)` is a different structure path ([image](/en/docs/web-device/markdown/image/)). ## Sample contract | Field | Value | | --- | --- | | Purpose | Document-target `media` image with caption | | Boundaries | No video/audio product promise on this page; trust/whitelist for arbitrary embeds is separate; missing `src` → placeholder | | Author entry | Generic leaf directive `::media{…}` (Markdown → AUP `type: media`) | | Surface | Web Device **document** | | Public status | `released` | | Fallback / failure | Missing `src` → empty placeholder figure; unsupported type falls through to image rendering | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (image) This sample uses the generic Markdown → AUP path (`::media` → `type: media`). The asset is a static documentation image URL used elsewhere on this site. It is **not** evidence of video, audio, avatar, or unrestricted third-party embedding. Source: ```markdown ::media{id="docs-prim-media-img" type="image" src="https://media.arcblock.io/lib/2f/2f757138def2b3fc.w1600.webp" alt="Illustrative documentation asset" caption="Document-target media illustration"} ``` Rendered: ::media{id="docs-prim-media-img" type="image" src="https://media.arcblock.io/lib/2f/2f757138def2b3fc.w1600.webp" alt="Illustrative documentation asset" caption="Document-target media illustration"} ### Failure and limits | Situation | Expected result | | --- | --- | | Missing `src` | Empty `aup-media` placeholder (no broken remote load as the sample contract) | | Unknown `type` | Falls through to image rendering path | | Expecting frame / iframe embed API | Wrong surface — use `::embed` / frame rules | | Inline `![alt](src)` | Separate MD structure path, not this AUP `media` node sample | Source (missing `src` — placeholder only): ```markdown ::media{id="docs-prim-media-empty" type="image" alt="Missing source becomes a placeholder"} ``` Rendered: ::media{id="docs-prim-media-empty" type="image" alt="Missing source becomes a placeholder"} Minimal AUP JSON shape (interactive / full-web authoring; same renderer keys): ```json { "id": "hero-shot", "type": "media", "props": { "type": "image", "src": "/assets/example.png", "alt": "Example", "caption": "Caption" } } ``` ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `media` | | Implementation | `content-reader.ts` (generic directive → type name); `renderer/primitives/media.ts` | | Public routes | `/en/docs/aup/primitives/media/` · `/zh/docs/aup/primitives/media/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · open routes; confirm figure + caption and empty placeholder | | Accept | Image sample shows figure/caption; empty `src` is placeholder; page does not claim video/audio/frame | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `overlay` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/overlay/ `overlay` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `overlay` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `experimental` | | Document capability | `unsupported` | | Shared degradation chain | overlay → text | | Author entry | AUP session / interactive Web (Showcase `overlays`) | | Document renderer / notes | No dedicated document renderer for full overlay chrome; chain degrades to text | | Showcase evidence | `blocklets/showcase-dsl/.aup/pages/overlays.aup` | ## When to use Alert, confirm, toast, HUD, or multi-step choice UI on a target that reports overlay support. ## When not to use Do not put live overlay samples on static docs. Document cannot host modal interaction chrome. ## Document sample **Not provided.** `DEVICE_CAPS_DOCUMENT` leaves `overlay` at the default `unsupported`. Shared chain: `overlay` → `text`. Public docs must not fake modal/toast UI. Author and accept overlays on an interactive AUP session (Showcase `overlays` page), not on this site’s static document target. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `rtc` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/rtc/ `rtc` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `rtc` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported` | | Document capability | `unsupported` | | Shared degradation chain | rtc → unsupported | | Author entry | AUP on targets with realtime media capability | | Document renderer / notes | Not on document RENDERERS as a native path | | Showcase evidence | Not a document sample; interactive runtime only | ## When to use Realtime audio/video collaboration on a device that grants media permissions. ## When not to use Never claim RTC from static documentation. Chain has no useful document fallback. ## Document sample **Not provided.** Shared chain: `rtc` → `unsupported` (explicit). Static docs must not simulate camera/mic UI as product capability. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `surface` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/surface/ `surface` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `surface` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `unsupported (document)` | | Document capability | `unsupported` | | Shared degradation chain | No shared chain | | Author entry | AUP / widget surface mounts on supporting runtimes | | Document renderer / notes | Document unsupported; see frames/surfaces docs for Web Device mounts | | Showcase evidence | Interactive surfaces / comments-surface etc. (widgets may host surfaces) | ## When to use Host a named interactive surface mount in an AUP tree where the runtime defines that surface. ## When not to use Do not equate AUP `surface` with Web Device `surfaces/*` layout mounts (docs-page, pagination, …). Different layers. ## Document sample **Not provided.** Document capability is `unsupported`. No shared degradation chain invents a safe stand-in. For Web Device page chrome surfaces, use Web Device documentation — not this primitive page. ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `table` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/table/ `table` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `table` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `released` | | Document capability | `native` | | Shared degradation chain | Empty AUP table → “No data” body (not a degradation chain) | | Author entry | AUP tree (`columns`/`rows`) · GFM pipe tables (Markdown path, often HTML text) | | Document renderer / notes | `renderer/primitives/table.ts` | | Showcase evidence | report / finance compositions; GFM path verified on document unit pages | ## When to use You need semantic columns and rows as an AUP `table` node, or a static GFM table in content Markdown. ## When not to use Do not confuse a **chart** degradation table with an author-written table. GFM tables are not a deep AUP `table` props contract. ## Sample contract | Field | Value | | --- | --- | | Purpose | Static columnar content in docs (GFM path) | | Boundaries | Not an editable grid; not chart fallback chrome; not every AUP table prop combination | | Author entry | Pipe table in Markdown | | Surface | Web Device **document** | | Public status | `released` (GFM path verified) | | Fallback / failure | Malformed pipes → ordinary Markdown / broken table; empty AUP table → “No data” (AUP path) | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (GFM table) This is the Markdown/GFM path on the document target. It is **not** a live claim of every AUP `table` prop combination. Source: ```markdown | File | Purpose | Writes data | | --- | --- | --- | | `content.md` | Content item | No | | `layout.aup` | Page layout | No | ``` Rendered: | File | Purpose | Writes data | | --- | --- | --- | | `content.md` | Content item | No | | `layout.aup` | Page layout | No | Unit page: [GFM table](/en/docs/web-device/markdown/gfm-table/). ### AUP node shape (source-only on this page) Interactive / full-web authoring uses explicit `columns` / `rows`. Empty AUP tables render a “No data” cell. That string is table empty-state chrome, not proof of a chart. ```json { "id": "rates", "type": "table", "props": { "columns": [ { "key": "name", "label": "Name" }, { "key": "value", "label": "Value" } ], "rows": [{ "name": "alpha", "value": "1" }] } } ``` ### Failure and limits | Situation | Expected result | | --- | --- | | Malformed pipes | Ordinary Markdown / broken table, not a runtime error surface | | Empty body rows in GFM | Author content only — no automatic “No data” chrome from the chart chain | | Assuming AUP `table` props from a GFM sample | Wrong path depth; write AUP JSON/DSL when you need that node | | Chart degradation table | Separate unsupported chart path — not this sample | ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `table` · GFM table | | Implementation | `content-reader.ts` (table case); `renderer/primitives/table.ts` | | Public routes | `/en/docs/aup/primitives/table/` · `/zh/docs/aup/primitives/table/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · open routes; compare source fence to rendered table | | Accept | Source and rendered table match; no edit controls; no chart claim | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `text` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/text/ `text` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `text` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `released` | | Document capability | `native` | | Shared degradation chain | None (document reports native) | | Author entry | AUP tree · Markdown blocks · GFM callouts → text admonition | | Document renderer / notes | `renderer/primitives/text.ts` (includes admonition) | | Showcase evidence | Markdown body path; admonition labels via `content-reader.ts` `ADMONITION_LOCALIZED_LABELS` | ## When to use You need semantic text, headings (`level`), code/quote formats, badges, or admonitions. ## When not to use Do not use `text` to smuggle layout chrome or site hero copy contracts that belong to Web Device components. ## Sample contract | Field | Value | | --- | --- | | Purpose | Static callout / admonition presentation on document | | Boundaries | Not editable; not a toast/overlay; not a full AUP `text` props reference for every format | | Author entry | `> [!NOTE]`-style blockquote (Markdown → document text admonition) | | Surface | Web Device **document** | | Public status | `released` | | Fallback / failure | Unknown marker → ordinary blockquote; bare marker uses locale default title | | Verification | Routes below · `arc --version` = `2.0.0-beta.28` | ## Document sample (admonition via GFM) On the document target, a GitHub-style callout becomes text-admonition presentation. This proves the Markdown → document path for callouts. It is **not** a full AUP `text` node props reference (`level` / `format` / `variant` live in AUP JSON/DSL). Source (custom title on the marker line): ```markdown > [!NOTE] Portable copy > This callout is document content. It does not run actions or write AFS data. ``` Rendered: > [!NOTE] Portable copy > This callout is document content. It does not run actions or write AFS data. Source (bare marker — label comes from locale defaults): ```markdown > [!TIP] > Prefer a same-line custom title when the English word is not the label you want. ``` Rendered: > [!TIP] > Prefer a same-line custom title when the English word is not the label you want. Bare markers use the reader’s default label for the content locale. English keeps English defaults; **zh** defaults are applied at read time (`NOTE`→说明, `TIP`→提示, `IMPORTANT`→重要, `WARNING`→警告, `CAUTION`→注意). An explicit same-line title always wins. ### Failure and limits | Situation | Expected result | | --- | --- | | `[!FIXME]` or other unknown marker | Plain blockquote, not callout chrome | | Marker not on the first line of the quote | Not recognized as admonition | | Expecting dismiss / editor controls | Static document content only | | Assuming this is AUP `format: markdown` inside an interactive page | Wrong surface; that path is not this sample | Unit page for the structure alone: [GFM admonition](/en/docs/web-device/markdown/gfm-admonition/). ## Verification evidence | Item | Value | | --- | --- | | Baseline | `2026-08-09` · `arc --version` → `2.0.0-beta.28` | | Capability row | `docs/aup/capability-matrix.md` (internal, non-routed) · `text` · GFM admonition | | Implementation | `content-reader.ts` (`ADMONITION_MARKER_RE`, `ADMONITION_LOCALIZED_LABELS`); `renderer/primitives/text.ts` | | Public routes | `/en/docs/aup/primitives/text/` · `/zh/docs/aup/primitives/text/` | | Local run | `arc service start --blocklet blocklets/arcblock --port 4900` · open routes; on zh locale, bare markers show Chinese default titles | | Accept | Source matches rendered callout; unknown marker stays a quote; no edit controls | ## Evidence anchors | Item | Value | | --- | --- | | Registry | `packages/aup/src/aup-types.ts` · `AUP_PRIMITIVES` | | Document caps | `providers/runtime/web-device/src/device-caps.ts` · `DEVICE_CAPS_DOCUMENT` | | Degradation | `packages/aup/src/degradation.ts` · `DEGRADATION_CHAINS` | | Internal matrix | `docs/aup/capability-matrix.md` (internal, non-routed) | | Taxonomy hub | [Primitive taxonomy and evidence](../../primitive-support-matrix/) | | Sample contract rules | [Live examples: scope and contract](../../live-example-contract/) | ## Nearby pages - [All primitives](../) - [Device capabilities and degradation](../../device-capabilities-degradation/) - [Custom primitives and Web widgets](../../custom-primitives-web-widgets/) - [Semantic tree](../../semantic-tree/) --- ## `time` primitive URL: https://www.arcblock.io/en/docs/aup/primitives/time/ `time` is an **AUP cross-device primitive**, not a Web Device layout component and not a Web-only widget. It is one of the 18 names in `AUP_PRIMITIVES` and appears in every target's `DeviceCaps.primitives` map as `native`, `webview`, `partial`, or `unsupported`. ## Contract | Field | Value | | --- | --- | | Primitive name | `time` | | Layer | AUP cross-device primitive (`AUP_PRIMITIVES`) | | Public status | `experimental` | | Document capability | `partial` | | Shared degradation chain | time → text (when unsupported) | | Author entry | AUP tree / DSL · generic Markdown `::time{…}` | | Document renderer / notes | `renderer/primitives/time.ts` (`