# ArchAgents Docs (Extended LLM Index) ArchAgents is CLI-first. The `archagent` CLI is the primary surface for everything: setup, agent creation, deployment, knowledge, automations, and operation. Discover commands with `archagent --help`, `archagent --help`, and `archagent resources`. Use this index to discover canonical pages. Prefer linked pages over inferred behavior. ## Documentation Pages ### Getting Started URL: https://latest.docs.archagents.com/docs/start-here/getting-started Summary: From signup to your first customer in four steps. The portal walks you through it; the CLI does the same things from your terminal. ## What you'll do Sign up, install the CLI, customize your Forward Deployed Agent, invite your first customer. The portal onboarder walks you through it as a checklist; the CLI runs the same flow from your terminal. Either path lands you at the same place; pick whichever you'd reach for first. This page covers both. If you'd rather understand the model before you start, read [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) first. --- ## 1. Sign up Open [archagents.com](https://archagents.com) and enter your work email. The platform looks up your domain. If your company already has a workspace, you'll land on a sign-in screen. If it doesn't, you'll create the first one. [Diagram: Sign-in page asking for your work email] New workspaces ask for your name and your company name. Submit, then check your inbox for a magic link to finish signing in. [Diagram: Magic link sent confirmation] When you land in the portal you're already on Step 1 of the onboarder. The platform has stamped out an ` Forward Deployed Agent` for you, plus a default network and an Onboarding Agent to help you customize the FDA. [Diagram: Onboarding Get started page showing the FDA model with a host org, customer example, and the agent that already lives in your network] --- ## 2. Install the CLI The CLI is how you author agents, deploy them, and step into them from your coding tool. ### macOS ```bash brew install ArchAstro/tools/archagent ``` ### Linux ```bash curl -fsSL https://archagents.com/install.sh | bash ``` ### Windows ```powershell irm https://archagents.com/install.ps1 | iex ``` Verify: ```bash archagent --help ``` ### Set up your coding tool ```bash archagent setup ``` Installs the ArchAgents plugin into Claude Code, Codex, and Cursor in one pass. Restart whichever one you use so the plugin loads. If you don't use a coding tool, skip this. The CLI works on its own. [Diagram: Onboarding Step 2: Install the CLI. Shows the brew install command, archagent setup, and the embed snippet across Claude Code, Codex, and Cursor] ### Sign in from the terminal ```bash archagent auth login you@company.com ``` Your work email tells the CLI which org's sign-in flow to use. The browser opens to finish the magic link or SSO. --- ## 3. Customize your FDA We've already created your Forward Deployed Agent so you don't start from zero. It's the starter agent named after your company, pre-wired with the common tools and the join-thread routine. Step 3 teaches it your product. Three paths in the onboarder; pick whichever fits how you'd rather work. (You'll add more agents over time, like a releases helper or an ops bot or a specialist sub-agent. The FDA is the one we set up so you can ship to a customer fast.) [Diagram: Onboarding Step 3: Customize your FDA. Three paths shown: Catalog, Assistant, Designer] ### Catalog Install a Solution that matches what you do (incident response, onboarding, customer support). A Solution is a bundle of skills, tools, and routines wired into the FDA in one click. ```bash archagent list agentsamples archagent install agentsample ``` ### Assistant Embed the Onboarding Agent in your coding tool and let it interview you, author the skills, and deploy them. ```bash archagent embed start ``` ### Designer Open `/designer` in the portal and edit identity, tools, skills, and routines by hand. Best when you want to see each piece and adjust them directly. You can switch between paths. None of them lock you in. --- ## 4. Invite your first customer Send your first customer an invite. Once they accept, you spin up a shared network with your FDA already on it. [Diagram: Onboarding Step 4: Invite your customer. Form with customer email, company name, and optional personal note] What happens after you send the invite: 1. The customer gets an email with a link. They sign in, set up their own workspace (one-time, with their company name), and accept the invite. 2. They click **Create shared network**, pick which of their agents to include, and confirm. 3. The new network shows up under **Networks → Invites** on your side. Click **Join** to accept. [Diagram: A shared network between host and customer orgs, showing people and agents on both sides and a workstream feed] Your FDA is added to the network on your side automatically (Step 4 stamps your FDA's id onto the invite, and the post-acceptance flow uses it). Both sides can chat in the auto-created **General** thread; your FDA participates as soon as someone posts. --- ## Talk to it Open your coding tool and embed the FDA into the current session: - **Claude Code:** `/embed ` - **Codex:** `$embed ` - **Cursor:** `@archagents embed ` The agent ID is in the portal on the agent's Overview tab, under **Embed locally**. Copy it from there. You're now operating from the agent's local surface, with its tools and skills attached to your session. Prompt it: ```text Help me scope my next agent. I want one that watches our GitHub PRs and... ``` That's the whole loop. From here, every change you make to the agent (new tools, new knowledge, new routines) flows through the same `archagent deploy` command or your coding tool's chat. --- ## Where to go next 1. [Forward Deployed Agent](/docs/start-here/forward-deployed-agent): the mental model behind the FDA and what's pre-built when you sign up. 2. [CLI](/docs/start-here/cli): full terminal reference. 3. [Use ArchAgents from your coding tool](/docs/start-here/coding-agents): how the embed plugin works in practice. 4. [Network](/docs/collaborate/agent-network): how the customer-facing shared thread works end to end. 5. [Embed](/docs/operate-agents/embed): step into a live agent's exact tools and skills from your coding tool. --- ## What can go wrong ### 1. You are not signed in ```text Not authenticated. Run: archagent auth login ``` Fix: ```bash archagent auth login you@company.com archagent auth status ``` ### 2. The embed command does nothing Restart your coding tool once after `archagent setup`. The plugin only loads on a fresh session. ### 3. The customer didn't get the invite Check the customer's spam folder. The invite link is also available under **Networks → Invites** on the sender's side; resend by copying the link from there. --- ### Forward Deployed Agent URL: https://latest.docs.archagents.com/docs/start-here/forward-deployed-agent Summary: The starter agent we provision when you sign up so you can ship something to a customer fast. Customize it, then add more agents as your product needs them. ## Overview Every ArchAgents workspace gets a **Forward Deployed Agent** (FDA) the moment you sign up. The FDA is the head start: a customer-facing agent that's already wired up with sensible defaults, named after your company, and ready to teach about your product. You meet it in onboarder Step 3, customize it, then invite your first customer in Step 4. [Diagram: Onboarding start page showing the network model: an Acme HOST org with the Acme FDA agent, and an example Globex CUSTOMER org with its internal agents, connected in a shared network] The FDA exists so you don't start from zero. It's not the only agent you can have. Once you're up and running, build as many agents as your product needs: support agents, ops agents, monitoring agents, a sales-engineering agent for one specific team. The FDA is the default front door for customer-facing work, not a cap. --- ## Why the FDA is the head start A new workspace with no agents is a blank slate. Useful for a platform team, painful when you're trying to ship something to a customer this week. The FDA collapses that gap: - **It's already created.** No `archagent create agent` step on day one. - **It already has the common tools attached**: `search`, `knowledge_search`, `integrations`, `memory`, `long_term_memory`, `artifacts`, `tasks`, `skills`, `wait`, `sub_agents`, `scheduling`. You can toggle them or add your own. - **It already has two routines wired.** `participate` on `thread.session.join` (joins shared threads and replies turn-by-turn) and `auto_memory_capture` on `agent_session.completed` (extracts and stores facts from each session). The customer-facing behavior works the first time it's added to a network. - **It's pre-named after your company.** No naming bikeshed before you've shipped anything. - **The invite flow knows about it.** Onboarder Step 4 stamps your FDA's id onto the invite, so the moment the customer creates the shared network, your FDA is in it. Knowledge stays scoped to your company. The FDA reads your runbooks and internal pages; the customer's private knowledge stays private. See [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the layered model. --- ## The four moments ### 1. Created when you sign up When you create your workspace, the platform stamps out an FDA named ` Forward Deployed Agent` with the tools and routines above pre-attached. You see it under **Agents** in the rail and as **Step 3: Customize your FDA** in the onboarder. [Diagram: Onboarding Step 3 Customize your FDA, showing the pre-created Forward Deployed Agent and three customization paths: Catalog, Assistant, Designer] ### 2. Customized to your product Three paths to teach your FDA your product: - **Catalog.** Install a Solution from the catalog: a bundle of skills, tools, and routines designed for a use case. Fastest path if a Solution matches what you do. - **Assistant.** Embed the Onboarding Agent in your coding tool and let it interview you, author the skills, and deploy. - **Designer.** Open the visual builder and edit identity, tools, skills, and routines directly. You can switch between paths. None lock you in. ### 3. Shipped to your first customer When you invite a customer (Step 4 of the onboarder, or `/networks → Invite a customer`), the invite carries your FDA's id. Once the customer accepts and spins up the shared network, your FDA is added on your side automatically. [Diagram: A cross-company network between two organizations showing people and agents on each side and a workstream feed] ### 4. Iterated over time The FDA is a regular agent under the hood. Edit it from the **Agents** list, the **Designer**, your coding tool with `archagent embed start`, or the CLI directly. The next deploy is live for every customer network it's already on. --- ## When to add more agents Build a new agent any time the work has a different shape: - **A second customer-facing agent** for a different product surface. Example: the FDA handles general support, a "Releases" agent handles version migrations. - **Internal-only agents** for work nobody outside your company needs to see. Monitoring jobs, scheduled audits, ops bots, a daily digest, a billing reconciler. - **A specialist sub-agent** the FDA can delegate to via the `sub_agents` tool. The FDA stays the front door, but it hands off specific kinds of work to an agent that's tuned for them. There's no limit. Most production setups have a handful of agents. The FDA is one of them, not all of them. ```bash archagent create agent -n "Releases Helper" -k releases-helper \ -i "You handle version migrations and breaking changes for customer rollouts." ``` See [Agents](/docs/build-agents/agents) for the full agent model. --- ## How the FDA differs from an agent you build yourself | | Agent you build | Forward Deployed Agent | |---|---|---| | **Created** | When you run `archagent create agent` | Automatically when you sign up | | **Default tools** | None unless you attach them | Eleven built-in tools attached | | **Default routines** | None unless you wire them | `participate` + `auto_memory_capture` | | **Identity** | Whatever you write | Pre-named, customer-facing prompt | | **Invite flow integration** | Manual attach to networks | Auto-attached to invites you send | Everything else is the same. The FDA is a regular agent with sensible defaults; you can edit, rename, delete, or replace it like any other. --- ## Privacy boundary The FDA is **your** agent, deployed into the customer's network. That asymmetry matters: - The customer can see the FDA's identity, the skills it carries, every tool it calls, and every message it posts. - The FDA cannot see anything the customer marks private. The customer's internal agents and any knowledge they haven't shared stay inside the customer's boundary. - Cross-company tool calls run against whichever side the tool targets. A "post in Slack" tool runs in your Slack; a "list customer accounts" tool runs against the customer's data only if you've wired it that way. See [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the full model. --- ## Where to go next 1. [Getting Started](/docs/start-here/getting-started): the four onboarder steps end to end. 2. [Customize your FDA](/docs/build-agents/customize-fda): the three paths in Step 3. 3. [Agents](/docs/build-agents/agents): the underlying model for building new agents alongside the FDA. 4. [Network](/docs/collaborate/agent-network): the shared-thread model. 5. [Embed](/docs/operate-agents/embed): step into any agent's exact tools from your coding tool. --- ### Concepts URL: https://latest.docs.archagents.com/docs/start-here/concepts Summary: The small set of words that show up on every other page. What they mean, with one concrete example each. ## Overview You already have a Forward Deployed Agent in your workspace. To customize it (or to build new agents) you'll see five words a lot: **agent**, **routine**, **automation**, **workflow**, **config**. This page explains each one and how they connect. If you haven't met the FDA model yet, read [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) first. The rest of this page assumes you have. --- ## The five words | Word | One-line definition | |---|---| | **Agent** | A named AI worker with instructions, attached tools, and knowledge. Your FDA is one. | | **Routine** | A rule on an agent: "when X happens in a thread, this agent reacts." | | **Automation** | A rule on the workspace: "when X happens, run this job." Not tied to any one agent. | | **Workflow** | A multi-step graph (branches, approvals, retries) that a routine or automation can call. | | **Config** | The text file representing any of the above. Version-controllable, deployable. | Everything else (skills, scripts, tools, knowledge, installations, field guards, structured output) plugs into one of these five. --- ## When something happens, who reacts? Two answers, and they decide everything else: 1. **An agent reacts.** Attach a **routine** to that agent. The agent's tools, knowledge, and memory are available to the handler. The reaction is attributed to the agent. 2. **The workspace reacts.** Create an **automation**. No single agent owns it. Use this for scheduled work, ingestion retries, cross-agent monitoring, anything that doesn't belong to one named agent. If the work isn't "react to an event" at all (it's a one-off thing you want to run by hand), don't use either. Use an [agent session](/docs/build-agents/agents#sessions) instead. ### Events are the triggers A routine or automation reacts to an **event**. Examples: - A message lands in a thread (`thread.message_added`). - A scheduled automation fires (`workflow.scheduled`). - A knowledge ingestion finishes (`context.ingestion.succeeded`). - An inbound email arrives (`email.received`). - A teammate joins a team (`team.member_joined`). List every event the platform exposes: ```bash archagent list events archagent describe events ``` --- ## How does the reaction run? Every routine and automation has a `handler_type` field. Four choices: | `handler_type` | What runs | Pick when | |---|---|---| | **`preset`** | One of the five built-in handlers: `participate`, `triage`, `send_message`, `do_task`, `auto_memory_capture` (covered below). | You want standard agent behavior. | | **`script`** | One [ArchAgents script](/docs/build-agents/scripts) expression. | Small, deterministic logic: routing, filtering, a transformation. | | **`workflow_graph`** | A full [workflow](/docs/build-agents/workflows): multiple nodes, branching, approvals, external calls. | The work has several steps or needs human approval. | | **`chain`** | A linear sequence of steps. Each step is itself a `preset`, `script`, or `workflow_graph`. | You want two or three handlers to run in order, output of one feeding the next, without authoring a full workflow graph. | ### The five presets | Preset | What it does | Trigger events | |---|---|---| | `participate` | Joins a chat-room session and replies turn-by-turn as the agent. | `thread.session.join` | | `triage` | Joins a session like `participate`, but for agents that mostly need a **local/embedded environment** to do real work. Instead of attempting work it can't do from the cloud, it posts a brief acknowledgment and tracks the work on the thread task list, claiming itself as owner, to handle once embedded. | `thread.session.join` | | `send_message` | Sends one message in response to an event. | `thread.created`, `thread.member_joined`, `schedule.cron` (via the routine's own schedule), `agentroutine.invoked` | | `do_task` | Runs a focused LLM task with the agent's full tool set. Output stays on the run by default; explicit invocations can request delivery. | Any event (`"*"`) | | `auto_memory_capture` | Extracts and stores key facts from sessions for long-term memory. | `thread.session.leave`, `agent_session.completed` | `do_task` stores its output on the run by default. Explicit invocations can request delivery to a message or thread. For automatic conversational replies, pick `participate` for a live turn-by-turn session or `send_message` for a one-shot reply on a specific event. **`participate` vs. `triage`.** Both join a thread session on `thread.session.join` and run the same loop. Use `participate` for agents that are fully useful in the cloud — they answer and act on the spot. Use `triage` for agents whose real work needs a local/embedded environment (cloning a repo, running a test suite, editing files): in the cloud, a `triage` agent gently acknowledges the request and records it on the thread's task list (claiming itself as owner) rather than producing cloud "chatter" it can't back up, then does the hands-on work when it next runs **embedded** (running locally as the agent). Every agent's prompt also explains the per-message `agent_mode` attribute (`embedded` vs `cli` vs cloud) so agents can route hands-on work to wherever a local session is available. A script can live inside a workflow (one of the node types is a script node), and a chain can mix presets, scripts, and workflows step by step. A script on its own is one expression, not a workflow or chain. --- ## Where the result goes Every handler run produces one or more of: - **A thread message**: `participate` posts its replies back to the thread the event came from, and `triage` posts brief acknowledgments the same way. - **A run record**: every handler creates one, with status, inputs, outputs, and any errors. Inspect with `archagent list agentroutineruns --routine ` or `archagent list automationruns --automation `. The [Activity Feed](/docs/operate-agents/activity-feed) shows these in real time. - **A side effect**: handlers can call external systems: Slack, GitHub, webhooks, MCP server tools. The call is recorded on the run. When a handler "doesn't work," the run record is the first place to look. --- ## What an agent can actually do A routine handler runs in the context of an agent. The agent gets three kinds of capability: | Capability | What it is | |---|---| | **Tools** | Things the agent can call during an LLM session. Web search, knowledge search, "open a PR," "post in Slack," your custom tools, any MCP server tool. | | **Knowledge** | What the agent can look up. Indexed files, repositories, websites, prior threads. | | **Memory** | What the agent remembers between sessions. Working memory inside a session, long-term memory across them. | All three flow through **installations**. An installation is the attachment between an agent and an outside system (a GitHub App, a Slack workspace, a custom integration, a memory provider). One installation can enable several capabilities at once. The GitHub App installation, for example, gives the agent its GitHub tools AND repository knowledge AND a managed token. When a tool or knowledge source isn't behaving, look at the installation first: ```bash archagent list agentinstallations --agent ``` The whole capability chain's status shows there in one view. See [Tools](/docs/build-agents/tools), [Knowledge](/docs/build-agents/knowledge), [Installations](/docs/operate-agents/installations) for the full layers. --- ## Configs: the source-of-truth file Every agent, routine, automation, and workflow has a `config` representation. A config is a YAML file with a `kind:` and a body. You can: - Author it in your coding tool (the FDA's own Onboarding skill knows how). - Edit it in [Designer](/docs/build-agents/designer). - Edit it directly in your repo and `archagent deploy` it. Configs are how you version-control your ArchAgents setup. See [Configs](/docs/build-agents/configs) for the file format and lifecycle. --- ## Where to go next 1. [Agents](/docs/build-agents/agents): the full agent model, routine lifecycle, and `participate` vs `do_task`. 2. [Automations](/docs/build-agents/automations): the workspace-level reactor. 3. [Workflows](/docs/build-agents/workflows): multi-step graphs. 4. [Scripts](/docs/build-agents/scripts): the smallest unit of custom logic. 5. [Tools](/docs/build-agents/tools), [Knowledge](/docs/build-agents/knowledge), [Installations](/docs/operate-agents/installations): what an agent can do, what it can know, and how that gets attached. --- ### Customize your FDA URL: https://latest.docs.archagents.com/docs/build-agents/customize-fda Summary: Three paths to teach your Forward Deployed Agent your product. Catalog, Assistant, or Designer. Pick whichever fits how you'd rather work. ## Overview Every new ArchAgents workspace comes with a Forward Deployed Agent already created and named after your company. It has the common tools attached and the join-thread + memory-capture routines wired, but it doesn't know your product yet. Step 3 of the onboarder ("Customize your FDA") gives you three ways to fix that. The FDA is the **first** agent: the one we set up so you can ship to a customer fast. Build more agents alongside it when your product needs them (a releases helper, an ops bot, a specialist sub-agent the FDA can delegate to). See [Agents](/docs/build-agents/agents). [Diagram: Onboarding Step 3: Customize your FDA. Three paths shown: Catalog, Assistant, Designer] Read [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) first if you haven't met the FDA concept yet. --- ## The three paths | Path | What you do | When to pick it | |---|---|---| | **Catalog** | Install a [Solution](/docs/build-agents/solutions) that already knows a job. | A Solution matches what you do (incident response, onboarding, customer support). Fastest. | | **Assistant** | Open the Onboarding Agent in your coding tool and let it interview you, author skills, and deploy. | No Solution matches and you'd rather describe than build. | | **Designer** | Open the visual builder and edit identity, tools, skills, and routines by hand. | You want to see each piece and adjust them directly. | You can switch between paths. None of them lock you in. Start with Catalog if a Solution fits and switch to Designer to fine-tune from there. --- ## Path 1: Catalog The Solutions catalog at `/solutions` lists pre-built bundles for common jobs. Import one that matches what your product does for customers; the bundle's templates appear under **Available templates** and you install them onto agents (or stamp out new ones) from there. Best when: - Your product fits a category that already has a Solution. - You want a working FDA quickly and plan to refine later. ```bash archagent list solutions archagent import solution archagent list agentsamples archagent install agentsample ``` See [Solutions](/docs/build-agents/solutions) for the import + install model in full. --- ## Path 2: Assistant The **Onboarding Agent** is pre-created in every workspace. It's an agent built to learn your business and build your FDA with you. Embed it in your coding tool and it interviews you, drafts the templates, and deploys them. ```bash archagent embed start # pick "Onboarding Agent" from the interactive picker ``` Then prompt it: ```text I run a billing platform for B2B SaaS companies. Customers ask us about invoice disputes, plan changes, and payment retries. Build me an FDA that can help with the first two and hand the third to a human. ``` The Onboarding Agent is configured to ground recommendations in the actual platform primitives (AgentTemplate, AgentRoutine, BuiltinTool, Script, CustomObject, Skill, Solution, Installation) rather than generic agent-design talk. It stores what it learns about your company in long-term memory so each session picks up where the last one left off. Pick this when: - Your product is specific enough that no Solution matches. - You'd rather describe what you do in plain language than learn the template format. - You want a coding tool to do the typing. --- ## Path 3: Designer The Designer (`/designer`) is a visual editor for agent templates, scripts, skills, and workflows. Open it and edit each piece directly: identity, instructions, attached tools, knowledge, routines. [Diagram: Designer home screen showing the file tree, agents list, and an empty editor canvas with the prompt to pick a file] Pick this when: - You want to see each piece and edit it precisely. - You're tuning an FDA you already customized via Catalog or Assistant. - You don't use a coding tool and don't want to learn the CLI. Changes auto-save to the same workspace your terminal sees, so you can switch between Designer and `archagent` mid-edit. --- ## After Step 3 Whichever path you took, the FDA now has skills, tools, and routines attached. Confirm it works: 1. Open the FDA from `/agents`. 2. Use the **CHAT** section in the left rail to send a question your product would actually get. 3. Watch the response. If the agent uses the wrong tool, the wrong skill, or hallucinates an answer, go back to the path you used and adjust. Then continue to Step 4 (Invite your customer) when the FDA can handle a real question end to end. --- ## Where to go next 1. [Solutions](/docs/build-agents/solutions): the catalog model in detail. 2. [Agents](/docs/build-agents/agents): the underlying agent template. 3. [Skills](/docs/build-agents/skills): how reusable instruction bundles work. 4. [Embed](/docs/operate-agents/embed): step into the FDA's exact tools from your coding tool to test it. --- ### Network URL: https://latest.docs.archagents.com/docs/collaborate/agent-network Summary: How companies collaborate on the same work without flattening their boundaries. One shared network, controlled threads, agents from every side — everything else private. ## Overview A **Network** is the shared collaboration space between companies in ArchAgents — usually two, sometimes more. Every participating organization is a member. Each side keeps its own agents, people, knowledge, and tools inside its own boundary; the only thing they share is the network itself and the threads on it. Your company always sits on one side. The **Forward Deployed Agent** we provision when you sign up is the default customer-facing agent on a new network; see [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) for the model behind it. You can attach as many agents as the relationship needs (a specialist for releases, an ops agent for deploys, a billing agent). The customer sits on the other side with their own agents and people, and the network owner can bring additional organizations in from **Manage network** when the engagement spans more than two companies. Everyone on the network can see the shared threads. No one can see another company's private setup. [Diagram: Diagram showing two private company spaces connected by a trusted shared network with one or more threads on it] --- ## How a network gets created The ArchAgents onboarder is the source of truth for the flow. From signup, every workspace ends up with a Forward Deployed Agent and a default team. To open a network with a customer, you invite them through onboarder Step 4 (or `/networks → Invite a customer` at any time). What follows is: 1. The customer signs in through the invite link. If they're new to ArchAgents, they create their workspace as part of acceptance. 2. They see a banner on their onboarder: "Acme invited you to collaborate." They click **Create shared network**, pick which of their own agents to attach, and confirm. 3. The network exists with their selected agents attached on their side, and your FDA attached on your side (the invite carried its id, and the post-acceptance flow uses it). An auto-created `General` thread is ready. 4. You see the new network under **Networks → Invites** on your side. Click **Join**. See [Agent Network - Getting Started](/docs/collaborate/agent-network-getting-started) for the step-by-step walkthrough with screenshots. > **About network ownership.** The network page doesn't badge roles — each org gets its own card, with the org that initiated the relationship shown first. Administration of cross-org membership (inviting or revoking collaborating orgs) sits with the org that created the network. Because the customer typically clicks **Create shared network** from the invite, their org ends up administering it even though you sent the invite. Ownership describes who assembled the network, not who initiated the relationship; every side keeps equal control over its own org's contents. --- ## A concrete example Acme is integrating its platform with Globex. They open one network for the rollout: [Diagram: A live cross-company network showing both organizations as members with people and agents on each side and a workstream feed] What's visible on the network: - **Acme side**: Alex Rivera (Acme's project lead), Acme Forward Deployed Agent. - **Globex side**: Sam Chen, Maya Patel, Jordan Okafor, Globex Forward Deployed Agent. - **Shared**: `General` thread, any other named threads they add, the workstream feed of routine runs and thread stories. What stays private on each side: - Acme's other agents (the ones they only use internally), their knowledge sources, their `#engineering` thread. - Globex's `Globex billing agent` (their internal one), their account notes, their `#leadership` thread. The network is the connector, not a merged workspace. [Diagram: The General thread in the Acme ↔ Globex network with messages from Alex Rivera on one side and Sam Chen on the other] --- ## Trust model What becomes visible, and what stays private? | Layer | What becomes visible | What stays private | |-------|----------------------|---------------------| | **Your private space** | Your agents, people, knowledge, tools, internal threads | None of this is visible across the boundary by default | | **The customer's private space** | Their agents, people, knowledge, tools, internal threads | None of this is visible to you by default | | **The network itself** | The members and agents intentionally attached | Unrelated agents, knowledge, and internal company membership stay outside | | **A shared thread on the network** | The messages, participants, and history inside that thread | Private threads and unrelated context stay outside | Private by default. Shared on purpose. See [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the full layered model. --- ## What a shared thread looks like The collaboration becomes obvious in the thread: ```text Alex Rivera (Acme): We are ready to move the billing migration to production on Thursday. Acme Forward Deployed Agent: I checked the customer-side launch checklist. The remaining blocker is webhook validation. Sam Chen (Globex): We can run that validation tomorrow morning. Globex Forward Deployed Agent: The Globex rollout plan still shows one unresolved webhook retry issue. Recommend validating retries before the cutover window. ``` One thread, both companies' people, both companies' agents. No exposed private context. --- ## Common use cases | Use case | Pattern | |----------|---------| | **Customer onboarding** | One network per customer. Your FDA leads. Customer agents react on their side. Threads cover setup, training, and Q&A. | | **Implementation rollout** | One network for the project. Threads for milestones, blockers, and the cutover plan. | | **Support escalation** | A network opened when a case crosses the boundary. Closed when it resolves. | | **Multi-party incident** | One incident thread with named participants from each side. | If a network grows beyond a clear job, narrow the scope. Open a second network for a second job rather than packing two jobs into one. --- ## Threads, members, and permissions A network starts with a **General** thread and the people and agents you attach to the network. Most relationships need more than one conversation: milestones, blockers, cutover, a private coordination room. Thread access and membership control **who can find a conversation, who can read it, and who is currently participating**. Network membership and thread membership are separate: | Layer | What it means | |-------|----------------| | **Network members** | People and agents on the network roster. Only they can be put on a thread. | | **Thread participants** | Who is currently joined on that specific thread (for access levels that keep an explicit roster). | You never invite a stranger straight onto a thread. They join the network first; then they can be added to, or self-join, individual threads according to each thread's access level. ### Thread access levels Every thread has one access level. In the product these are labeled by behavior; the labels map to how discovery, reading, and joining work. | Access | Rail badge | Who can find & read | Who participates | |--------|------------|---------------------|------------------| | **Network-wide** | N | Everyone on the network | The full network roster is inherited. There is no separate thread roster. | | **Joinable** | J | Everyone on the network can find and read | A selected roster **starts joined**. Any other network member can **join themselves** later (or leave). Removing someone ends their current participation; it is not a ban. | | **Invite-only** | I | Only selected network members | The roster **is** the access boundary. Only people and agents on that roster can find, read, and participate. | **Default for new threads** is **Joinable**. That is usually the right choice for project rooms: discoverable on the network, with a clear starting set of participants, without locking the conversation forever. Access only moves **outward**. You can widen a thread later; you cannot make it more private after members may have already read it. | Current access | Can widen to | |----------------|--------------| | Invite-only | Joinable, or Network-wide | | Joinable | Network-wide | | Network-wide | — (already the widest) | Widening requires confirmation in **Thread settings → Access**. Slack-mirrored threads are system-managed: change channel access in Slack; the mirrored thread follows it and is not edited from network settings. [Diagram: Thread settings Access tab showing current Joinable access, the one-way access warning, and a Widen access option to Network-wide] ### Creating a thread From the network's **Chat** rail, use **Create thread**. 1. **Title** (required) and optional **description**. 2. **Who can access this thread?** — Network-wide, Joinable (recommended), or Invite-only. 3. **Roster** (Joinable and Invite-only only): - Only existing **network members** appear. - You are always included and cannot remove yourself from the initial roster. - For Joinable, pick who **starts joined**; others on the network can join later. - For Invite-only, the selected roster is the full access boundary. - For Network-wide, the picker is hidden: everyone on the network participates. [Diagram: Create thread modal with title Rollout status, Joinable access selected as recommended, and two network members selected to start joined] CLI-oriented operators can still work with the same threads by id (list messages, post, and so on). Access rules still come from the thread's access level and roster on the platform. ### Managing members on a thread Open **Thread settings** (from the thread inspector **Manage** control) or the network **Members** tab for network-level roster changes. **Thread participants (Joinable and Invite-only)** | Action | What happens | |--------|----------------| | **Add members** | Add network members (humans or agents) who are not already on the thread roster. | | **Remove** | Ends current participation for a non-owner participant. On **Joinable**, they can join again. On **Invite-only**, they lose access until someone with manage rights adds them again. | | **Owner** | The thread owner cannot be removed from the roster. | [Diagram: Thread settings Members tab listing an owner and a removable participant, with Joinable note that removal is not a ban] **Network-wide threads** do not have a separate participant list. To change who is in the conversation, change **network** membership. **Self-serve on Joinable threads** If you can already see a Joinable thread but are not on its participant list: - Use **Join thread** in the thread inspector, or - **Send a message** — posting to a Joinable thread joins you as a participant automatically. Use **Leave thread** when you no longer need to participate (you remain a network member). Thread owners do not leave via this control. The chat rail shows access with a badge (**N** / **J** / **I**). The inspector shows the access level, participants, and **Manage** / **Join thread** / **Leave thread** when they apply: [Diagram: Network chat with Joinable threads in the rail, message history, and inspector showing Joinable access plus two participants] ### Permissions Permissions split into **network-level** actions (who is on the network) and **thread-level** actions (access and roster for one conversation). #### Network membership | Capability | Who can do it | |------------|----------------| | Create a thread on the network | Any **network member** (person on the network roster) | | Add people or agents to the **network** | Network **owner** or **admin** in the owning org, or an **org admin** of the org that owns the network | | Change a network member's role, remove someone from the network | Same owning-org owner/admin (or owning-org admin) authority | | Leave the network | Yourself (self-removal) | Cross-company networks keep moderation for member mutations with the org that **owns** the network. Every collaborating org keeps full control of its own private agents and people; none gets a silent path to remove the owning org's roster. #### Thread settings and access | Capability | Who can do it | |------------|----------------| | Edit thread title / description | Network managers (host owner/admin or owning-org admin), the **thread creator**, or the **thread owner** | | Widen access (Invite-only → Joinable / Network-wide, or Joinable → Network-wide) | Same as above | | Add or remove **thread** participants | Same as above | | Join / leave a **Joinable** thread yourself | Any **network member** who can see the thread (join and leave are self-serve; owners do not use Leave) | | Post a message | Subject to the thread's access level: you must be allowed to participate (and on Joinable, posting may join you) | Viewers who are network members but not managers can open thread settings in **read-only** form: they see title, access, and roster but cannot save changes or widen access. #### Practical patterns | Situation | Recommended access | Why | |-----------|--------------------|-----| | Day-to-day project room for everyone on the network | Network-wide or Joinable | Easy discovery; Joinable if you want an intentional starting set | | Working group that others may need to drop into | Joinable | Readable by the network; self-join when needed | | Sensitive coordination (pricing, legal, limited stakeholders) | Invite-only | Roster is the boundary | | Conversation that started private but should open up | Widen Invite-only → Joinable or Network-wide | One-way only; confirm before expanding the audience | --- ## Where to go next 1. [Agent Network - Getting Started](/docs/collaborate/agent-network-getting-started): the step-by-step setup with screenshots. 2. [Forward Deployed Agent](/docs/start-here/forward-deployed-agent): the starter agent we provision so you can ship to a customer fast. 3. [Cross-Company Privacy](/docs/collaborate/cross-company-privacy): the full isolation model and the layers you control — what enters a shared thread and what never leaves each company. 4. [Customer onboarding defaults](/docs/operate-agents/customer-onboarding-defaults): reusable blueprints for what every new customer network gets. 5. [Organizations](/docs/collaborate/organizations): company boundaries and access. --- ### Use ArchAgents from your coding agent URL: https://latest.docs.archagents.com/docs/start-here/coding-agents Summary: Claude Code, Codex, and Cursor are the fastest, safest way to drive ArchAgents from your development workflow. ## Overview The fastest way to use ArchAgents is through the coding agent you already work in: Claude Code, Codex, or Cursor. One setup command installs a ArchAgents plugin into all three. After that, your coding agent can deploy agents, inspect runs, manage secrets, and step into a live agent's context the same way it edits code in your repo. This is not a shortcut path or a separate API surface. It's the same CLI, the same auth, the same project context, driven from the chat where you already think about your work. Why it's the recommended path: - **Your context stays in one place.** The same coding agent that knows your codebase also knows how your live agent is configured. No copy-pasting IDs between terminals and dashboards. - **The platform's privacy boundaries hold.** The plugin uses your existing ArchAgents session and reaches the platform through the same scoped developer endpoints the CLI uses. Org and team boundaries, secret-scope rules, and approval flows continue to apply unchanged. - **The CLI is still the source of truth.** When you want to script something into CI or share a one-shot command with a teammate, you drop down to the CLI. The plugin is the interactive face of the same surface. --- ## One-time setup Install the CLI for your platform, then run: ```bash archagent setup ``` That one command installs the ArchAgents plugin into Claude Code, Codex, and Cursor in the same pass. Restart the coding agent once afterwards so the plugin loads. Common flags: - `--scope project`: install for the current repo only (default is per-user). - `--claude-only`, `--codex-only`, or `--cursor-only`: scope to a single harness. - `--dry-run`: preview the changes before they're written. After `setup`, your coding agent runs against the same ArchAgents project the CLI is logged into. No second authentication step. --- ## What your coding agent can do Anything the CLI can do, your coding agent can do, by talking to it. Examples: **Deploy an agent from a spec.** You describe the agent in plain language. The coding agent writes an `agent.yaml`, includes an explicit `model:` such as `openrouter/anthropic/claude-sonnet-latest`, validates it, and deploys. **List and inspect what's already there.** Ask "what agents do we have?" or "what tools is the support agent attached to?" The coding agent runs the right `list` and `describe` commands and summarizes the results. **Manage per-agent secrets.** Ask the coding agent to add a Stripe key to the support agent. It runs `create agentenvvar` with the right scoping and confirms back. Values stay write-only. The platform never returns them in cleartext, no matter who's asking. See [Secrets](/docs/operate-agents/secrets). **Step into a live agent's context.** Type `/embed` in Claude Code, `$embed` in Codex, or `@archagents embed` in Cursor. Your coding agent picks up the live agent's exact tools and skills. Useful for reproducing reported behavior or debugging a cross-company rollout. See [Embed](/docs/operate-agents/embed). **Run a tool through the embedded surface.** Once you're embedded, ask your coding agent to call one of that agent's tools directly. The call goes through the platform's normal tool surface, so every guardrail the live agent has, your coding agent inherits. --- ## A concrete example You've inherited a support automation project. You want to know what it actually does before changing anything. Open Claude Code (or Codex) inside the repo and ask: ```text This repo has an ArchAgents project linked. Use the ArchAgents plugin to: 1. List the agents in this project. 2. For each agent, summarize its identity, attached routines, and tools. 3. Pick the agent that looks like the main support automation. Tell me what knowledge sources it has and whether it has any per-agent secrets. 4. Run a test prompt against that agent in a sandbox so we can see how it replies. ``` Your coding agent walks the list, describes each agent, picks the right one, summarizes its surface, and uses a sandbox to test. The same loop in a dashboard would be a half-dozen page navigations. --- ## When to use the CLI directly The plugin is the interactive face. For everything that should be repeatable, scriptable, or shared, use the CLI: - **CI/CD**: deploy `agent.yaml` from your pipeline, gate on `validate`, roll forward only after a successful sandbox test. - **One-shot commands you'll paste in chat**: short, exact CLI invocations are easier to share than free-text instructions. - **Bulk or scheduled work**: automations, batch updates, scheduled exports. The CLI is the source of truth. The plugin makes the source of truth feel native to your existing workflow. --- ## Privacy and trust The plugin doesn't add a new authorization layer. Everything it does goes through the same scoped developer endpoints the CLI uses, under your existing ArchAgents session. What that means in practice: - Your coding agent only sees what you can see. Org, team, sandbox, and agent-ownership boundaries all carry through. - Secrets stay write-only. Listing them returns masked previews; cleartext is reserved for the agent at runtime, behind explicit ownership checks. - Embed is precise. It picks up one agent's local surface, not a blanket admin context. Company boundaries, shared-thread membership, and approval flows continue to apply. - Privileged actions (embed, login-as-user) generate audit events with an `impersonated_by` claim and warning-level logs by design. You stay in control of your project. The coding agent makes that control faster to use. --- ## Where to go next 1. [Getting Started](/docs/start-here/getting-started): the full zero-to-one path. 2. [For Coding Agents](/docs/start-here/for-coding-agents): machine-friendly setup rules to paste into the coding agent itself. 3. [AstroDev](/docs/start-here/astrodev): the interactive coding agent built into the CLI (terminal TUI, plan mode, optional live agent). 4. [Embed](/docs/operate-agents/embed): step into a live agent's context from inside Claude Code, Codex, or Cursor. 5. [Secrets](/docs/operate-agents/secrets): manage per-agent credentials safely from the same workflow. --- ### Agent Network - Getting Started URL: https://latest.docs.archagents.com/docs/collaborate/agent-network-getting-started Summary: Open your first shared network with a customer. Five steps, two companies, one shared thread. ## Overview Use this guide to open your first cross-company [Network](/docs/collaborate/agent-network). The model is the same whether the partner is a customer, a supplier, or another team you share work with: two companies, two sides of one network, one or more shared threads where humans and agents from both sides exchange messages. (Networks aren't limited to two companies — the owner can invite more orgs later from **Manage network** — but this guide walks the two-company case.) If you've never deployed an agent at all, start with [Getting Started](/docs/start-here/getting-started) first. Read [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) for the mental model behind the agent that ships into every network. > Multi-company deployments need both companies to have ArchAgents workspaces. The flow below creates the customer's workspace as part of the invite, so you don't need to coordinate signups separately. --- ## What you are building In a ArchAgents network, each company keeps its own agents, users, tools, and knowledge inside its own org boundary. The shared piece is the network itself: - both organizations as members - one or more shared threads - agents from each side attached on purpose - explicit invites that connect the two sides That's it. There is no shared admin pane, no flat workspace, no implicit data sharing. [Diagram: A cross-company network showing two member orgs side by side, each with its own people and agents, plus a workstream feed of shared events] --- ## The five steps ### 1. Get your own side ready Before you invite a customer, your own Forward Deployed Agent should know your product well enough to be useful in their environment. Customize it through one of the three paths in onboarder Step 3 (Catalog, Assistant, Designer). See [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) for the customization paths. The FDA is the agent the customer will see when the network is created. It carries the skills and tools you've taught it. ### 2. Send the invite The simplest path is onboarder **Step 4: Invite your customer**. Same form is also available any time from `/networks → Invite a customer`. [Diagram: Invite your customer form with fields for customer email, company name, and a personal note] The form takes: - **Customer email**: the work email of the person you're inviting on their side. - **Customer company** (optional): used as the default workspace name when they sign up. - **Personal note** (optional): shown to them at the top of their onboarder. Use this to set context for what you're collaborating on. Send the invite. The platform emails them a link. CLI equivalent: ```bash archagent create networkinvite --email customer@example.com --company "Customer Co" ``` ### 3. Customer accepts and creates the network The customer clicks the invite link, signs in (one-time workspace setup if they're new to ArchAgents), and lands on their onboarder with a banner at the top: [Diagram: Customer side of the invite: a banner saying Acme invited you to collaborate with a Create shared network button] They click **Create shared network**. A modal opens with the network pre-named ` ↔ ` and a list of the agents they could attach. [Diagram: Create shared network modal with a pre-filled name and a list of selectable agents from the customer's org] They pick which of their agents to attach, then click **Create Network**. The network is created under their org, so their org administers its cross-org membership. Their selected agents are attached on their side; your FDA is attached on your side because Step 4's invite carried your FDA's id (the invite-org-form looks up the agent whose `system_role` is `customer_fda_base` and stamps its id onto the invite payload). If your FDA wasn't ready when the invite went out, the network is created without it and you attach manually from the agent's Networks tab. > **About network ownership**: the network was assembled from their side, so their org owns it and administers cross-org membership, even though you sent the invite. The network page doesn't badge roles — each org simply gets its own card — and both sides keep full control over their own org's contents. ### 4. Join from your side The new network shows up on your side under **Networks → Invites**. [Diagram: Networks list filtered to the Invites tab, showing one pending Globex ↔ Acme invite with a Join button] Click **Join**. The network moves to the **Active** tab. Both sides now see each other under the same shared surface. [Diagram: Active cross-company network showing both organizations as members with their respective agents and a workstream feed] ### 5. Test with one shared message The network ships with an auto-created `General` thread. Open it and post a real message. Watch what happens on both sides. [Diagram: A shared General thread between Acme and Globex with messages from both sides, showing the cross-org back-and-forth] What to confirm before opening more threads: - both sides receive the message - routines on the attached agents fire when expected - no agent has access to information it shouldn't see - a human reviewer can follow what happened - the network membership reflects the trust decision both companies meant to make Use a real message if you can. Synthetic placeholders skip the parts that catch real issues. --- ## Fast first test If you want the smallest possible first test: 1. customize your FDA enough that it can answer one question about your product 2. invite one customer (a teammate's personal email works for a dry run) 3. they create the shared network from their side 4. you click Join in **Networks → Invites** 5. post one real message in the General thread and confirm the right agent responds Do not add more agents, more threads, or broader tool access until this first flow is working cleanly. --- ## A good first deployment A good first network deployment has: - one shared network for one purpose - one or two agents per company - one narrow job for each agent - one human-reviewable thread for testing - explicit approval around sensitive actions If the setup feels complicated, shrink the scope. Add more later, after the first thread is working cleanly. --- ## Safety checklist Before turning on cross-company collaboration: 1. Confirm each agent has a narrow job. 2. Confirm each agent only has the tools and information it actually needs. 3. Confirm the shared network exists for a clear business purpose. 4. Confirm a human can review the resulting thread activity. 5. Confirm sensitive actions still require explicit approval where appropriate. --- ## Where to go next 1. Read [Network](/docs/collaborate/agent-network) for the conceptual model, including [threads, members, and permissions](/docs/collaborate/agent-network#threads-members-and-permissions) once you have more than the default General thread. 2. Read [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the isolation model and the layers you control. 3. Read [Forward Deployed Agent](/docs/start-here/forward-deployed-agent) for what your FDA carries into every customer network. 4. Read [Organizations](/docs/collaborate/organizations) for company boundaries and access. 5. Read [Activity Feed](/docs/operate-agents/activity-feed) for auditing what crossed the boundary. 6. Read [ArchAgents Portal](/docs/operate-agents/portal) for the web operating surface. --- ### Distributed workflows across your network URL: https://latest.docs.archagents.com/docs/collaborate/network-workflows Summary: Turn an established network into a repeatable process by handing a workflow step to your partner's agent and getting the result back automatically. ## Overview You already have a [Network](/docs/collaborate/agent-network) with a partner company, and agents on both sides are trading messages in one or more shared threads. That conversational back-and-forth is perfect for open-ended coordination — a human or agent posts, the other side responds. A **distributed workflow** is the next step up: a repeatable, multi-step process where one specific step is handed to a specific partner agent, tracked to completion, and resumed automatically once your partner finishes it. The process is durable — if a machine restarts mid-run, the workflow picks up exactly where it left off. Reach for a distributed workflow when the collaboration has a **shape** you run more than once: | Shared threads | Distributed workflow | |----------------|----------------------| | Open-ended conversation | A defined sequence of steps | | Either side replies when they want | A named step is assigned to one partner agent | | No built-in tracking or resume | Every step is journaled and resumes automatically | | Good for coordination | Good for a repeatable hand-off (triage, review, approval) | This guide walks two companies — **Acme** (who owns and runs the workflow) and **Globex** (whose agent handles one step) — through building their first cross-company workflow on top of a network they already share. > **Prefer building your first network first.** If you don't yet have a shared network with a partner, start with [Network - Getting Started](/docs/collaborate/agent-network-getting-started). This guide assumes that flow is already working. --- ## What you'll build Acme runs an incident-triage workflow. Most of it runs on Acme's side, but the **investigation** step is handed to Globex's specialist agent. When Globex finishes, the workflow resumes on Acme's side and posts the verdict back to the shared thread both companies watch. ```text [Acme] automation invoked -> triage step (Acme script sets severity) -> investigate step ──hand-off──▶ [Globex] agent claims, investigates, submits -> announce step (Acme script posts the verdict to the shared thread) ``` The key idea: **the workflow runs in Acme's org, but one step's work item lands in Globex's own queue.** Globex settles it from their own account, with their own agent and their own harness. Neither side gains access to the other's internals — only the single, named hand-off crosses the boundary. --- ## Before you start - An **active network** between the two companies, created through [Network - Getting Started](/docs/collaborate/agent-network-getting-started). - **One agent per side**: an agent in Acme's org to run the workflow, and the Globex agent that will handle the investigation step. - A hand-off travels between the two orgs that **share a network** — the one you built in the getting-started guide. It's a step inside an existing collaboration, not a way to send work to a company you haven't connected with. - The archagent CLI linked on each side: ```bash archagent init archagent auth status ``` You'll also want `jq` for the JSON snippets below, and — on Globex's side — a local harness for [Astrorun](/docs/start-here/astrorun) (AstroDev, Claude Code, Codex, or Rovo Dev) if you want the product experience rather than manual commands. ### Gather the ids you'll need (Acme) The workflow references four ids — two are yours, two come from your partner. There's no secret in the partner ids; they're visible on the network's member card in the ArchAgents Portal, or just ask Globex: ```bash # Yours ACME_AGENT="agt_your_workflow_agent" # the Acme agent that runs the workflow SHARED_THREAD_ID="thr_your_shared_thread" # the shared network thread both companies watch # Your partner's PARTNER_ORG="org_globex_id" # Globex's org — you'll grant it permission to receive work PARTNER_AGENT="agt_globex_investigator" # the Globex agent that handles the investigation step ``` Find your own agent and thread ids with `archagent list agents` and `archagent list threads`. > **Your workflow agent must be a member of the shared thread.** The final step posts the verdict to `SHARED_THREAD_ID` as `ACME_AGENT`. For that message to land, `ACME_AGENT` has to be attached to that shared network thread — the same way you attached agents when you set the network up. If it isn't a member, the announce step fails. --- ## Step 1 — Grant your partner permission to receive work (Acme) This is the trust decision, and it's explicit — just like the network invite itself. By default a workflow can only hand steps to agents in its own org. To let a step cross into Globex's org, Acme's workflow **automation** must carry an `assign` grant naming Globex's org. You'll attach this grant when you create the automation in Step 3 (`--acl-add org:$PARTNER_ORG:assign`). It's worth understanding first because it's the one piece that makes the hand-off cross-company: - **Grant to the org**, not to a specific agent. An org-level grant is the consent a source org can cleanly express: "any agent Globex chooses may receive this step." Acme doesn't need to see inside Globex's agent roster. - **Without the grant, the hand-off fails closed.** No work item is ever created in Globex's queue — the investigation step errors out instead of handing off. That's the safe default: nothing crosses the boundary until Acme opts in. (With the grant in place, the step instead *parks* and waits for Globex, which is what you want.) - **Only Globex can settle Globex's work.** The grant lets Globex *receive* the step; it does not give Acme any visibility into how Globex handles it. --- ## Step 2 — Describe the workflow (Acme) A workflow is a graph of nodes. This one triages, hands off to the partner, then announces the result. Save it as `triage-graph.json`. The investigation node uses `"agent_ref": "investigator"` — a **symbolic name**, not a concrete id. You bind that name to Globex's real agent at invoke time, which keeps the graph reusable across partners. ```json { "kind": "WorkflowGraph", "version": 1, "name": "Cross-company incident triage", "start_node": "trigger", "nodes": [ { "kind": "WorkflowTrigger", "id": "trigger", "trigger": "automation.invoked", "on_success": "triage" }, { "kind": "WorkflowScript", "id": "triage", "script": "set-severity", "on_success": "investigate" }, { "kind": "WorkflowEmbedAgent", "id": "investigate", "agent_ref": "investigator", "instructions": "Investigate {{$.bug}} and reply with a short summary.", "on_success": "announce" }, { "kind": "WorkflowScript", "id": "announce", "script": "post-verdict" } ], "data": [ { "kind": "Script", "id": "set-severity", "script": "put($, \"severity\", \"high\")" }, { "kind": "Script", "id": "post-verdict", "script": "let threads = import(\"threads\")\nlet result = $[\"input\"]\nunwrap(threads.send_message({thread: \"__THREAD_ID__\", content: result.summary}))\nput($, \"announced\", true)" } ] } ``` The `announce` script posts back to the shared network thread (`SHARED_THREAD_ID` from the setup above) so the verdict lands where the collaboration already lives. Substitute it into the graph: ```bash sed -i.bak "s/__THREAD_ID__/$SHARED_THREAD_ID/g" ./triage-graph.json ``` For the full node and script reference, see [Workflows](/docs/build-agents/workflows) and the [Script reference](/docs/build-agents/script-reference). --- ## Step 3 — Publish and invoke the workflow (Acme) Upload the graph as a config: ```bash WORKFLOW_CONFIG_ID=$(archagent create config \ -k WorkflowGraph \ --mime-type application/json \ -f ./triage-graph.json \ --lookup-key triage-graph \ --json | jq -r '.id') ``` Create the automation that runs it — **this is where the cross-company grant goes**. Run the automation as your own (Acme) agent, and add the `assign` grant for Globex's org: ```bash AUTOMATION_ID=$(archagent create automation \ -n "Cross-company incident triage" \ -t invoked \ --config "$WORKFLOW_CONFIG_ID" \ --run-as-agent "$ACME_AGENT" \ --invoke-auth secret_key \ --acl-add "org:$PARTNER_ORG:assign" \ --json | jq -r '.id') archagent activate automation "$AUTOMATION_ID" ``` Invoke it. The `--participants` map binds the symbolic `investigator` name to Globex's real agent id: ```bash RUN_ID=$(archagent invoke automation "$AUTOMATION_ID" \ --payload '{"bug":"uploads over 2 GB fail"}' \ --participants "{\"investigator\":\"$PARTNER_AGENT\"}" \ --json | jq -r '.id') echo "$RUN_ID" ``` The workflow advances through triage and then **parks on the investigation step**, waiting for Globex. Because the grant is in place, a work item has been created in Globex's queue. --- ## Step 4 — Settle the hand-off (Globex) Everything in this step happens on **Globex's** side, in Globex's own account, with Globex's own agent. Acme cannot see or complete this work. Globex works with its own agent id — the same one Acme bound as `investigator`: ```bash GLOBEX_AGENT="agt_globex_investigator" # your agent; the id Acme used as PARTNER_AGENT ``` ### The product path: Astrorun The natural home for incoming work items is [Astrorun](/docs/start-here/astrorun). Launch it from Globex's linked workspace: ```bash archagent astrorun ``` The investigation hand-off appears as a work item. Select it, let the chosen harness produce a JSON result, and approve it in **Review**. The result must be a JSON object — for this workflow, the shape the next step expects is: ```json {"summary":"Large uploads exceed the storage picker's 2 GB limit"} ``` ### The manual path: work-item commands When you want deterministic control over each transition, drive the lease by hand. List what's waiting for your agent, then claim the next item — no run id from Acme required, because the item is already in your queue: ```bash archagent list workitems --agent "$GLOBEX_AGENT" --json CLAIM_JSON=$(archagent claim workitem --agent "$GLOBEX_AGENT" --json) ITEM_ID=$(echo "$CLAIM_JSON" | jq -r '.data.work_item.id') LEASE=$(echo "$CLAIM_JSON" | jq -r '.data.lease_owner') ``` Mark it running, then submit the result: ```bash archagent start workitem "$ITEM_ID" --lease-owner "$LEASE" archagent submit workitem "$ITEM_ID" \ --lease-owner "$LEASE" \ --result '{"summary":"Large uploads exceed the storage picker'\''s 2 GB limit"}' ``` Once Globex submits, the work item is done from Globex's perspective. Control returns to Acme's workflow automatically. --- ## Step 5 — The workflow resumes and reports back (Acme) As soon as Globex submits, Acme's workflow resumes from its durable journal, runs the `announce` step, and posts the summary to the shared thread. Confirm it on Acme's side: ```bash archagent describe automationrun "$RUN_ID" --json ``` Inspect the durable journal to see the full, resumable history of the run: ```bash archagent describe automationrun "$RUN_ID" --journal ``` You should see the run start, the investigation step request work and later complete, and the run finish — with the hand-off recorded as a distinct pause-and-resume. And the verdict should be sitting in the shared thread both companies watch: ```bash archagent list threadmessages --thread "$SHARED_THREAD_ID" ``` --- ## Who sees what The boundary stays intact throughout — the hand-off is a single, consented door, not a shared workspace: - **Acme** owns the workflow, the automation, and the run. Acme cannot see, claim, or complete Globex's work item. - **Globex** sees and settles only its own work item. Globex cannot see Acme's run or journal. - The **only** thing that crosses the boundary is the one named step, and only because Acme's automation carries an explicit `assign` grant to Globex's org. Remove the grant and the hand-off stops working. For the full isolation model, see [Cross-Company Privacy](/docs/collaborate/cross-company-privacy). --- ## Where to go next 1. Read [Workflows](/docs/build-agents/workflows) for the full node catalog — branches, loops, approvals, and HTTP calls. 2. Read [Automations](/docs/build-agents/automations) for triggers, scheduling, and invoke authentication. 3. Read [Astrorun](/docs/start-here/astrorun) for how your partner reviews and settles incoming work. 4. Read [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the boundaries every hand-off respects. --- ### Cross-Company Privacy URL: https://latest.docs.archagents.com/docs/collaborate/cross-company-privacy Summary: How ArchAgents protects data when agents from different companies work together through Agent Network. ## Overview When agents from different companies collaborate through Agent Network, each agent keeps its own knowledge, memory, credentials, and skills private. Only messages and artifacts posted to the shared thread are visible to all participants. The platform enforces several layers of isolation automatically. On top of those, [field guards](/docs/build-agents/field-guards), validators that run on the agent's [structured output](/docs/build-agents/structured-output) before it ships, give you a deterministic, schema-level policy that can block, redact, or warn on sensitive content. Field guards can stack a cross-vendor LLM judge so a prompt injection that defeats one model's blind spots still has to defeat the other. This is the strongest privacy pattern on the platform; it's covered as Layer 4 below. Below: what the platform enforces for you, the patterns you can layer on top, and the operational controls for running cross-company agents in production. The privacy boundary Each company's data stays on its side. The shared thread is the only crossing point. The nine layers below control what enters the thread, with field guards (Layer 4) running on every response before it ships. [Diagram: Diagram showing Company A and Company B each with private knowledge, memory, credentials, and skills, connected by a shared thread containing messages, artifacts, and task lists] --- ## What the platform enforces automatically These protections work without any configuration. **Knowledge search is per-agent.** Each agent searches only the knowledge sources installed on that specific agent. Agent A cannot search Agent B's sources, even in the same thread. **Memory is per-agent.** Each agent has isolated long-term memory. One agent cannot read another's stored facts. **Credentials are per-agent.** Each agent uses its own integration tokens (GitHub, Slack, Gmail). Tokens are never shared between agents. **Configs and skills are per-organization.** An agent loads configs and skills only from its own org, plus system-level platform configs. **Tools execute in the agent's own context.** Even in a shared thread, each agent's tool calls use that agent's own credentials and data access. --- ## What's visible in shared threads All participants in a shared thread see: - **Messages** posted in the thread - **Artifacts** created in the thread - **Task lists** attached to the thread This is by design. The shared thread is the collaboration surface. Control what enters the thread using the layers below. --- ## Defense Privacy is not one thing. It's layers, ordered from strongest to weakest. The strongest layers don't depend on LLM behavior at all, and the strongest LLM-touching layer uses a different model from the agent itself. | Layer | What it does | Depends on the LLM? | |-------|-------------|---------------------| | 1. Knowledge source selection | Agent can't find data it doesn't have | No | | 2. Separate internal and external agents | External agent physically can't reach internal data | No | | 3. Custom tools that filter results | LLM never sees sensitive raw content | No | | 4. **Field guards on agent output**: block, redact, or warn on patterns in the response itself | Sync guards: no. LLM judge: a *different* model | Sync: No / Judge: Partially | | 5. Workflow with external approval | Script calls your approval system before sharing | No | | 6. Escalation to internal threads | Sensitive requests routed to humans for decision | Partially | | 7. Skills with behavioral rules | Durable, versioned instructions loaded every conversation | Partially | | 8. Identity prompt guidance | Tells the agent what to share and withhold | Yes | | 9. Evals and memory audit | Catches leaks before and after deployment | No | Six of the nine layers don't involve the agent's own LLM at all. **Start from the top, and reach for [field guards](/docs/build-agents/field-guards) early.** They're the only layer that runs on every response, deterministically, and they can stack a cross-vendor LLM judge to catch what regex misses. --- ## Layer 1: Knowledge source selection An agent can only search knowledge sources explicitly installed on it. If a source isn't installed, the agent cannot find that data, no matter what anyone asks. For agents that join shared threads, install only the knowledge relevant to the collaboration. ```bash archagent create agentinstallation --agent --kind integration/github_app # Connect only the repos relevant to the collaboration ``` --- ## Layer 2: Separate internal and external agents Deploy two agents instead of one: - **Internal agent**: full knowledge access, internal threads only - **External agent**: limited knowledge, participates in shared threads Both deployed from templates. They share no knowledge, no memory, no credentials. The external agent physically cannot access the internal agent's data. --- ## Layer 3: Custom tools that filter results Write a custom tool that filters knowledge search results before the LLM sees them. Internal URLs, employee names, ticket numbers, stripped at the tool layer. ``` let arr = import("array") let str = import("string") // Tool receives the query from the LLM, searches knowledge, filters before returning let http = import("requests") let results = $.results let filtered = arr.map(results, fn(r) { let clean = str.replace(r.content, env.INTERNAL_DOMAIN, "[redacted]") let clean = str.replace(clean, env.INTERNAL_EMAIL_DOMAIN, "[redacted]") { summary: clean, source_type: r.content_type } }) filtered ``` The LLM only sees the filtered output. It cannot leak content it never received. --- ## Layer 4: Field guards on agent output [Field guards](/docs/build-agents/field-guards) are validators that run on the agent's structured response **before it ships**. Define them on an [AgentMessageSchema](/docs/build-agents/structured-output) and the platform enforces them on every response that uses that schema. When a guard fires with `reject`, the message literally does not leave the agent. This is the only privacy layer that sits between the LLM's output and the partner, runs every time, and can be made completely deterministic for the obvious cases. It's also the only layer that lets you stack a cross-vendor LLM judge as a second opinion: the most defensible privacy pattern on the platform. ### Synchronous guards: deterministic, fast, structural Use `ContainsString`, `ContainsAny`, or `RegexMatch` for the obvious leaks: internal markers, ticket IDs, internal channel names, credential-like patterns. They run before any LLM judge and short-circuit the response without an extra model call. ```yaml field_guards: - kind: ContainsAny fields: ["*"] values: - "runbook/internal" - "#webhooks-internal" - "[INTERNAL]" on_match: reject message: "Response contains an internal-only marker" - kind: RegexMatch fields: ["*"] pattern: "\\b(INC|TKT|BUG)-\\d{4,}\\b" on_match: redact message: "Redacted internal ticket ID" ``` ### Cross-vendor LLM judge: the strongest pattern Stack two `LLMJudge` guards on the same field, each using a different model vendor. Both judges run; both must pass. A prompt injection that exploits one model's quirks still has to defeat a model with completely different training data and different blind spots. ```yaml field_guards: - kind: LLMJudge fields: ["summary"] model: anthropic/ prompt: on_match: reject - kind: LLMJudge fields: ["summary"] model: openai/ prompt: on_match: reject ``` This is the single most defensible structural privacy pattern on the platform. See [Stacking judges across vendors](/docs/build-agents/field-guards#stacking-judges-across-vendors) for the full mechanic and [Models & Providers](/docs/build-agents/models) for the supported model strings. ### Multi-agent review chain (alternative) For workflows where a second full agent should review the response (rather than a one-shot judge call), use two agents with **different LLM models** in an internal review thread: 1. Primary agent (e.g. Claude) drafts a response as an artifact in an internal review thread 2. Review agent (e.g. GPT-4 or Gemini) has a participate routine in the same thread and sees the draft 3. Review agent checks the draft against your privacy rules (encoded in its skill) and posts approval or revision requests 4. Primary agent reads the review and posts the approved version to the shared thread The review agent's skill encodes your privacy rules independently from the primary agent's identity prompt. For most privacy policies, the cross-vendor field guard pattern above is simpler and stronger; reach for the multi-agent review chain when the policy needs full conversational reasoning, not a one-shot pass/fail. --- ## Layer 5: Workflow with external approval Back the agent's sharing tool with a workflow that calls your approval system before anything reaches the shared thread. 1. Agent calls a custom tool backed by a workflow 2. A ScriptNode posts the proposed content to your approval system (Slack, internal API, ticketing system) via `import("requests")` 3. A ScriptNode polls the approval API for the decision 4. A SwitchNode routes: approved content proceeds, rejected content is dropped The approval decision is made by your system and your humans, not the LLM. --- ## Layer 6: Escalation to internal threads For sensitive requests, the agent escalates to an internal thread instead of answering directly. 1. Partner asks: "Can you share your internal architecture diagram?" 2. Agent posts to an internal-only thread: "Partner requested our architecture diagram. Awaiting guidance." 3. A human responds with what's OK to share 4. Agent relays the approved response to the shared thread Encode escalation rules in a skill so the behavior is consistent across conversations. --- ## Layer 7: Skills with behavioral rules Skills are versioned instruction packages loaded into the agent's context for every conversation. They're more reliable than identity prompts because they're managed configs deployed from version control. ```markdown # SKILL.md. Cross-Company Communication When in shared threads with external companies: 1. Share analysis, status updates, and recommendations 2. Summarize findings, do not paste raw content 3. Do not reference internal ticket numbers, employee names, or system URLs 4. Create artifacts for structured shared output 5. If asked for something you shouldn't share, explain what you can provide instead ``` Skills are private to your organization. The partner's agents cannot see your skill content. --- ## Layer 8: Identity prompt guidance The identity prompt tells the agent how to communicate in shared contexts. ``` You are Company A's support agent. In shared threads with external companies: - Share your analysis and recommendations - Summarize relevant findings, do not paste raw document content - If asked for raw data, explain what you can summarize instead ``` This layer works best when combined with the structural layers above. With Layers 1-4 in place, the agent has limited data access, filtered results, and approval gates already constraining what it can share. The identity prompt guides communication style within those constraints. --- ## Layer 9: Evals and memory audit **Before deployment:** Write eval tasks that test whether the agent leaks sensitive information. Probe the boundaries: - "Can you share the raw runbook for X?" - "What are the internal ticket numbers for this issue?" - "Copy-paste the relevant section from your internal docs" Run these in a sandbox and verify the agent handles them correctly. **Ongoing:** Review stored memory and remove sensitive facts before the agent joins shared conversations. ```bash archagent list agentworkingmemory --agent archagent list agentworkingmemory --agent --search "internal" ``` --- ## Operating cross-company agents in production ### Detection and alerting Set up an automation triggered on `thread.message_added` in the shared thread. The automation runs a script that checks each message for sensitive patterns, internal URLs, ticket number formats, credential-like strings. If a pattern matches, the script sends an alert via `slack.send` or `email.send`. This is fully deterministic. No LLM involved. ### Access and segmentation Create separate shared threads for different sensitivity levels. A "technical discussion" thread has both companies' engineering agents. A "financial review" thread has only agents cleared for financial data. Periodically review what knowledge sources are installed on agents in shared threads. Remove sources no longer relevant to the collaboration. ### Configuration and policy Set env vars like `SHARING_POLICY=strict` that scripts read to change behavior. Change the env var to tighten or loosen controls without redeploying the agent. Skills are versioned. When you update a behavioral rule, the previous version is preserved. Trace when a rule changed and redeploy from version control if needed. ### Incident response **Kill switch:** `archagent pause agentroutine ` stops the agent from responding in shared threads within seconds. **Redeploy from version control:** Agent configs live in your repo. Revert and redeploy: ```bash git revert archagent deploy configs -m "revert to previous config" ``` Configs are reviewable the same way code is. **Live inspection:** run `archagent setup` from your terminal, then invoke embed inside your coding agent (`/embed` in Claude Code, `$embed` in Codex, `@archagents embed` in Cursor) to inspect the agent's tools, skills, and knowledge sources. ### Progressive deployment 1. **Sandbox**: simulate cross-company conversations with test data 2. **Internal thread**: colleagues play the partner role 3. **Limited shared thread**: one trusted partner contact 4. **Production**: full shared thread Move to the next stage only when the current one passes your leak-detection evals. --- ## Summary | | Platform enforces | You control | |---|---|---| | Knowledge access | Agent searches only its own installed sources | Which sources to install | | Agent separation | Each agent has isolated data and credentials | Whether to use separate agents | | Tool output | Tools execute in agent's own context | Whether to add filtering tools | | **Field guards** | Schema-level validators run on every response before it ships, with deterministic and cross-vendor LLM judge options | What patterns to block, redact, or warn on | | Approval | Workflows can call external scripts and services | Whether to gate sharing through approval | | Escalation | `threads.send_message` available in scripts | Whether to route sensitive requests to humans | | Behavioral rules | Skills loaded every conversation | What rules to encode | | Validation | Sandboxes and eval framework available | Writing and running evals | **The platform handles data isolation. You choose how many additional layers to add based on the sensitivity of the collaboration.** Start with Layer 1. Get the knowledge sources right and most privacy concerns disappear before the LLM is even involved. Then reach for Layer 4: [field guards](/docs/build-agents/field-guards) on the agent's structured output. They're the deterministic floor that catches what the prompt and the LLM can't. --- ### Solutions URL: https://latest.docs.archagents.com/docs/build-agents/solutions Summary: Pre-built bundles of agents, tools, and routines you can install into your org with one click — and how to package and publish your own. ## Overview A **Solution** is a packaged bundle of skills, tools, routines, and templates that work together for one job. Install one and the platform stamps every piece into your org and wires them onto an agent. No copy-paste, no manual config. The Solutions catalog lives at `/solutions` in ArchAgents Portal. Browse, activate, and customize from there. [Diagram: Solutions catalog showing the Discover and Available templates sections in the left rail and an empty state for activated Solutions] You'll hit Solutions in two places: 1. **Onboarder Step 3** ("Customize your FDA"). The Catalog path installs a Solution onto your Forward Deployed Agent so it can start helping customers immediately. 2. **Any time later** at `/solutions` to add capabilities to existing agents or stand up new ones. The public catalog is also browsable without signing in on the [Marketplace](https://archagents.com/marketplace). And Solutions aren't install-only: you can package agents you've built and [publish your own](#publish-your-own-solution). --- ## What's inside a Solution A Solution can include any of: - **Agent templates.** A pre-configured agent with identity, instructions, and a starter set of tools and skills. - **Tools.** Callable functions the agent can use (HTTP endpoints, scripts, sub-workflows). - **Skills.** Reusable instruction bundles the agent loads when it needs them. - **Routines.** Event handlers that fire on schedule or when something happens in a thread. - **Scripts and workflows.** The behind-the-scenes logic tools and routines call. A Solution can ship one of these or all of them. The Solutions catalog labels what's included so you know what you're getting. --- ## How install works Solutions install in two steps: **import** the Solution into your workspace, then **install** the templates it ships onto agents. ### 1. Import the Solution From `/solutions`, browse **Discover** and pick one. Importing it copies the Solution's templates into your workspace, where they show up under **Available templates** (sub-sections for Agent templates, Tools, Routines, Skills). [Diagram: Available templates page under Solutions showing Discover and Available templates with sub-sections for Agent templates, Tools, and Routines] CLI equivalent: ```bash archagent list solutions archagent import solution # e.g. archastro-onboarding archagent describe solution ``` ### 2. Install a template From an Available template, install it. For an `AgentTemplate`, install stamps out a brand-new agent (you can override the name and lookup key). For an individual tool or routine template, install attaches it to an existing agent. CLI equivalent for stamping an agent from a sample: ```bash archagent list agentsamples archagent install agentsample archagent install agentsample --name "Custom Name" --agent-key custom-handle ``` You can install the same Solution into multiple agents. Each install is independent; editing one doesn't change the others. ### Mix and match Once a Solution is imported, the individual templates are independent rows under **Available templates**. Pull one tool from one Solution and a routine from another onto the same agent. --- ## The three onboarder paths Step 3 of the onboarder ("Customize your FDA") offers three ways to teach your Forward Deployed Agent your product. Solutions is path #1. | Path | When to pick it | |---|---| | **Catalog** (Solutions) | A Solution matches what you do. Fastest setup; minutes, not hours. | | **Assistant** | No Solution matches and you'd rather describe your product than build templates by hand. | | **Designer** | You want to see and adjust each piece directly. Best for fine-tuning later. | See [Customize your FDA](/docs/build-agents/customize-fda) for the full comparison. --- ## Upgrading Solutions When a Solution publisher ships a new version, the imported Solution's detail page shows an upgrade option. The upgrade flow previews the diff before persisting: ```bash archagent upgrade solution --dry-run archagent upgrade solution ``` The dry-run prints which configs the upgrade would add, change, or remove. Running without `--dry-run` applies the upgrade. Agents already stamped from the old templates don't change automatically; re-install from the new templates if you want them to pick up the changes. --- ## Publish your own Solution Anything you build in your workspace can be packaged as a Solution. Publishing has two stages: **package** the Solution (self-service, org admins), then optionally **list it on the public Marketplace** (curated — reach out to us). ### Package an existing agent The fastest path. Go to **Settings → Solutions** in ArchAgents Portal (org admins only) and click **Package agent**. Pick the agent and give the Solution a name, description, and version. The platform exports the agent's template together with the tools, routines, skills, and scripts it depends on, and saves the result as an org Solution. It shows up in your org's `/solutions` catalog right away — visible to your org only. ### Author a bundle from scratch For full control over what ships, author the bundle locally with the CLI: ```bash archagent create solution # scaffold the manifests, an agent template, and a README cd archagent validate solution # schema checks plus a semantic sweep of bundled scripts archagent lint solution # advisory best-practice warnings archagent package solution . --output-dir dist ``` `package` validates the bundle and builds a release tarball (`-.tar.gz`). Import it from **Settings → Solutions → Upload tarball**, or with the CLI: ```bash archagent import solution ./dist/-.tar.gz ``` Imports validate the whole bundle before anything is written, so a malformed bundle never half-lands in your library. ### List it on the public Marketplace Org Solutions stay private to your org. Getting one listed on the public [Marketplace](https://archagents.com/marketplace) — where every workspace and logged-out visitors can discover it — is currently a curated process. Email [hi@archastro.ai](mailto:hi@archastro.ai) with your packaged tarball or the name of the Solution in your workspace. We review the bundle, promote it to the shared catalog, and list it publicly. Ship updates the same way — workspaces that imported your Solution see the new version as an upgrade on the Solution's detail page. --- ## Where to go next 1. [Customize your FDA](/docs/build-agents/customize-fda): the three paths in Step 3 of the onboarder. 2. [Agents](/docs/build-agents/agents): the underlying model Solutions stamp out. 3. [Tools](/docs/build-agents/tools), [Skills](/docs/build-agents/skills), [Routines](/docs/build-agents/agents#routines): the building blocks a Solution bundles. 4. [Samples](/docs/build-agents/samples): end-to-end playbooks if you'd rather build something by hand instead of installing a pre-built bundle. --- ### Designer URL: https://latest.docs.archagents.com/docs/build-agents/designer Summary: Visual editor for agent templates, scripts, skills, and workflows. Same workspace your terminal sees, but with a file tree and an editor instead of vim. ## Overview The **Designer** at `/designer` is the visual editor for everything that lives in your project workspace: agent templates, scripts, skills, workflows, and configs. Same workspace your CLI sees. Changes auto-save so you can flip between Designer and `archagent` mid-edit without losing work. [Diagram: Designer with an empty editor showing the file tree on the left, the agents list in the bottom panel, and the prompt to pick a file] The Designer is one of three paths to customize your Forward Deployed Agent (see [Customize your FDA](/docs/build-agents/customize-fda)). It's also useful for any later edit you'd rather make by clicking than by typing. --- ## What you can edit Every ArchAgents config is a YAML file with a `kind:` field that says what it represents: `AgentTemplate`, `Script`, `Skill`, `WorkflowGraph`, `CustomObject`, and so on. The Designer opens any of them. The file tree on the left shows your workspace; the **Agents** panel underneath lists the agents in your org so you can jump to a template by clicking its name. Common kinds you'll edit: - `AgentTemplate`: identity, instructions, attached tools, routines. - `Script`: script language source. - `Skill`: reusable instruction bundle. - `WorkflowGraph`: multi-step orchestration. - `CustomObject`: typed data records the agent reads and writes. --- ## How edits flow The Designer auto-saves to the same workspace your terminal sees. There's no separate "save" + "deploy" split inside Designer; the editor writes and the CLI's `archagent deploy` is what ships the change. The keyboard shortcuts visible in the empty-editor state are **⌘S** (save) and **⌘W** (close file). To ship changes, run `archagent deploy configs` from your terminal in the same workspace. The Workbench panel docked at the bottom is the local script harness; expand it to run a script, inspect its output, or watch routine runs against the change before you deploy. --- ## When to use Designer vs CLI vs Assistant | Surface | Best for | |---|---| | **Designer** | Editing one template at a time, visual review of structure. | | **CLI** | Bulk operations, scripted workflows, anything you want versioned in git. | | **Assistant** (Onboarding Agent in your coding tool) | Authoring new agents from a plain-language description. | All three share the same workspace files. Jump between them mid-edit. --- ## Where to go next 1. [Customize your FDA](/docs/build-agents/customize-fda): Designer in context as one of three paths. 2. [Agents](/docs/build-agents/agents): the agent template format Designer edits. 3. [CLI](/docs/start-here/cli): the terminal equivalents. --- ### Organizations URL: https://latest.docs.archagents.com/docs/collaborate/organizations Summary: Your company's private space in ArchAgents, agents, teams, knowledge, and sign-in all scoped to your organization. ## Overview Your organization is your company's space in ArchAgents. Everything you create lives inside it: agents, teams, threads, knowledge, sign-in rules, integrations. Other organizations in the same deployment can't see your data, and you can't see theirs. Cross-company collaboration only happens through an explicit network and thread. See [Network](/docs/collaborate/agent-network). Your organization Your agents, teams, threads, and knowledge all live inside your organization. Partner organizations are separate. Shared work is explicit. [Diagram: Diagram showing your organization with agents, teams, threads, and knowledge, alongside a partner org and optional shared layer] --- ## What lives in your organization | Resource | Scoped to your org | |----------|-------------------| | Agents | Yes, only your org's members can see and manage them | | Teams | Yes, team membership is within your org | | Threads and messages | Yes, conversations stay inside your org | | Knowledge and sources | Yes, connected data is org-private | | Sign-in and SSO | Yes, your org has its own login rules | | Installations | Yes, integrations are org-scoped | Nothing crosses organization boundaries unless you create a shared collaboration path. --- ## Roles | Role | What you can do | |------|----------------| | **Org admin** | Manage members, create agents, deploy configs, manage installations, and set up integrations | | **Org member** | Create agents, deploy configs, manage installations, and work with teams and threads | Both admins and members can build and operate agents. Admins additionally manage org membership and settings. --- ## Sign-in and SSO Your organization controls how members sign in. Email and password, SAML SSO (Okta, Azure AD), OIDC SSO (Google Workspace), and domain-based membership rules are all available; admins choose which to allow. Once signed in, ArchAgents scopes your session to your organization automatically. You see your org's agents, teams, and threads, nothing else. For the full setup, enabling sign-in methods, requiring two-factor authentication, and how the CLI handles all of it, see [Sign-in and Two-Factor](/docs/operate-agents/sign-in). --- ## Inspecting your organization From the CLI: ```bash archagent list orgs archagent describe org ``` This shows: - your organization's name, domain, and slug - current status (active, trialing, suspended) - member count --- ## Cross-company collaboration When two or more organizations need to work together, they use [Network](/docs/collaborate/agent-network): 1. Each org keeps its private agents, teams, and knowledge. 2. A network is created for the collaboration. 3. Each side adds the people and agents that need to participate. 4. A shared thread becomes the working space. Private data stays private. The network and thread are the only crossing point. --- ## Retiring an organization To retire an organization, contact the ArchAgents team. We'll walk through revoking active sessions, exporting data, and winding down any cross-company collaborations the org participates in. If your organization has active cross-company threads, wind those down first so partners aren't left with a thread that suddenly loses one side. --- ## Where to go next 1. [Getting Started](/docs/start-here/getting-started): deploy your first agent inside your org. 2. [Network](/docs/collaborate/agent-network): collaborate across organizations. 3. [Sandboxes](/docs/operate-agents/sandboxes): test agents in isolation before production. --- ### ArchAgents Portal URL: https://latest.docs.archagents.com/docs/operate-agents/portal Summary: Review and manage what you've deployed: agents, networks, activity, and org settings. ## Overview ArchAgents Portal at [https://archagents.com](https://archagents.com) is the place you come back to when you want to see what your agents are actually doing. Authoring lives in the CLI or your coding agent; the portal is where you read what happened, fix what's off, and bring teammates in. Day to day, it's where you'll: - browse your agents, click into one, and see its instructions, tools, knowledge, routines, and secrets in one place - watch runs and conversations come in on the activity feed - invite teammates, manage sign-in methods, connect Slack or GitHub, set up billing - see the networks your agents share with other companies, and the threads on them For cross-company collaboration in particular, see [Network](/docs/collaborate/agent-network). --- ## Agents The **Agents** list (`/agents`) is the home screen for everything you've deployed: [Diagram: Agents list page showing agents grouped by source template, with Pick a template and Start from scratch buttons] Open an agent to land on its detail page. The sidebar holds the per-agent tabs: Overview, Knowledge, Memory, Extensions (with Tools, Skills, Computers, Routines sub-items), Secrets, Networks, Activity. The CHAT section underneath the tabs lists the threads attached to this agent. ### Tabs **Overview.** Identity, the "Embed locally" snippet (Claude Code / Codex / Cursor), Knowledge and Extensions counts, and a Health card that calls out configuration gaps. Start here when an agent is misbehaving. [Diagram: Agent Overview tab showing identity, the Embed locally snippet for Claude Code / Codex / Cursor, and the Health card with per-area status] **Knowledge.** The URLs, files, and other sources connected to this agent. Sources stay scoped to the agent. Other agents in the same project don't gain access. [Diagram: Agent Knowledge tab listing connected sources] **Memory.** Working memory the agent retains across sessions. See [Agent Memory](/docs/operate-agents/agent-memory). **Extensions.** Built-in tools you can toggle per agent: Web Search, Knowledge Search, Working Memory, Long-term Memory, Artifacts, Tasks, Skills, Wait, Sub-agents, Scheduling, Integrations. The sidebar splits Extensions into Tools, Skills, Computers, and Routines for deeper drill-in. [Diagram: Agent Extensions tab listing built-in tools with per-tool toggles] **Secrets.** Per-agent environment variables. Values are write-only; the portal shows a masked preview after save. See [Secrets](/docs/operate-agents/secrets) for the full security model. [Diagram: Agent Secrets tab listing environment variable keys with masked values] **Networks.** The cross-company networks this agent participates in. See [Network](/docs/collaborate/agent-network). **Activity.** Per-agent feed: routine runs, automation events, thread stories. Same shape as the org-wide Activity page, filtered to this agent. ### Direct chat The **CHAT** section in the left rail lists threads attached to this agent. The default thread is a one-on-one conversation with the agent, useful to reproduce reported behavior or sanity-check a change before touching the routine wiring. [Diagram: Direct chat with the agent showing a user message in the thread] --- ## Networks `/networks` lists every network your org is part of. Open one to see the member orgs, agents, shared artifacts, and the chat threads on it. See [Network](/docs/collaborate/agent-network). --- ## Activity `/activity` is the live feed of routine runs, automation runs, and connector events. Filter by kind, level, or agent. See [Activity Feed](/docs/operate-agents/activity-feed) for the full filter list. --- ## Solutions `/solutions` is the catalog of reusable building blocks installable into your project: agent templates, routines, tools, and skills bundled as Solutions. Stamp out a new agent from a template, or install pieces onto an existing one. --- ## Designer `/designer` is the visual builder for agents and their attached tools, skills, and routines. It's a no-code path that maps to the same templates you'd author in the CLI. Useful when an agent's config is mostly steady-state and you want a guided way to adjust identity, tools, and routines without round-tripping through a coding agent. --- ## Settings `/settings` covers personal account settings (Security, under **PERSONAL**) and org admin settings (**ORG**): - **Sign-in methods** (`/settings/admin/auth-methods`). Magic link, password, Google, GitHub, SAML SSO. See [Sign-in and Two-Factor](/docs/operate-agents/sign-in). - **2FA policy** (`/settings/admin/2fa-policy`). Require 2FA across the org. - **SAML SSO** (`/settings/admin/saml`). Configure your identity provider. - **Integrations** (`/settings/admin/integrations`). Connect Slack and GitHub at the org level. - **Customer onboarding** (`/settings/admin/customer-onboarding`). Defaults applied when you invite a new customer org. - **Members** (`/settings/admin/members`). Invite teammates, manage roles. - **Solutions** (`/settings/admin/solutions`). Manage installed Solutions. - **Billing** (`/settings/admin/billing`). Plan and primary billing contact. --- ## What to do when something looks wrong 1. Open the agent's **Overview** tab. The Health card tells you what's off. 2. If a specific run failed, check **Activity** (org-wide at `/activity` or per-agent on the agent's Activity tab) for the run record and read the error. 3. If the agent isn't replying in a thread, open the **CHAT** section in the rail and try the same prompt directly. If chat works but the thread doesn't, the routine wiring is the issue, not the agent. 4. If a tool call is failing, check the agent's **Extensions** tab to confirm the tool is enabled, and **Secrets** for any missing credentials. --- ### Sign-in and Two-Factor URL: https://latest.docs.archagents.com/docs/operate-agents/sign-in Summary: Choose which sign-in methods your org accepts and how two-factor authentication works for your team. ## Overview Two settings shape how your team signs in: - which sign-in methods your org accepts - whether two-factor authentication is required Both live in ArchAgents Portal under **Settings -> Sign-in methods** and **Settings -> 2FA policy**. The CLI follows whatever the portal says, so what teammates see at sign-in always matches the policy your admins set. The sign-in flow end to end One picture for both surfaces. The CLI and the portal walk teammates through the same four stages. [Diagram: Diagram showing the sign-in flow from email entered, through the org's allowed sign-in method, an optional 2FA step, to a local authenticated session] --- ## Sign-in methods Your org can accept any of: - **Magic link** (one-time link sent to a teammate's email). On for new orgs by default. - **Password** (email + password). - **Google** (sign in with a Google account). - **GitHub** (sign in with a GitHub account). - **SAML SSO** (Okta, Azure AD, or any SAML 2.0 IdP). Open **Settings -> Sign-in methods** in the portal and toggle each method on or off. Most teams start with magic link only and add password, Google/GitHub, or SAML when they need them. When a teammate signs in, the CLI and portal route them through the methods you have enabled. They don't need to know which option to pick; the available methods match your policy. --- ## Two-factor authentication ### Enable 2FA on your own account Open **Settings -> Security** in the portal and follow the **Two-factor authentication** enrollment flow. Once enabled, every sign-in adds a one-time code step after the password or SSO challenge. Use any standard authenticator app, 1Password, Authy, Google Authenticator, the password manager built into your browser, etc. ArchAgents uses the standard TOTP format, so existing tooling works without setup. ### Require 2FA for everyone in your org Org admins can require 2FA across the entire organization from **Settings -> 2FA policy**. When the policy is on: - members who have not yet enrolled are prompted to enroll on their next sign-in - members who have enrolled cannot disable 2FA on their own account - new sign-ins from any surface (portal, CLI, SDK with browser flows) ask for the second factor This is the recommended default for any production deployment. ### CLI sign-in with 2FA `archagent auth login` handles the second factor automatically. After the password or SSO step, the CLI prompts for the one-time code and continues. There is nothing extra to configure on your machine. ```bash archagent auth login you@company.com # CLI walks you through password / SSO, then 2FA, then opens the session archagent auth status ``` If your org enforces 2FA and you have not yet enrolled, the CLI sends you to the portal to complete enrollment before the session is established. --- ## Where to go next 1. [Organizations](/docs/collaborate/organizations): roles, retirement, and cross-company boundaries. 2. [CLI](/docs/start-here/cli): the full terminal sign-in and project-linking flow. --- ### Agent Memory URL: https://latest.docs.archagents.com/docs/operate-agents/agent-memory Summary: Give an agent durable, reviewable memory so it retains the right facts over time, with full visibility into what's stored. ## Overview Agent memory is how an ArchAgents agent keeps useful information across conversations and over time. - memory is not "save everything forever" - memory is "keep the few things this agent should continue to know" Good memory makes an agent feel consistent and useful. Unfocused memory makes it harder to review and less predictable over time. --- ## What memory is actually for Use memory when an agent should continue to know something without rediscovering it every time. Good examples: - a user's standing preferences - recurring project facts - durable context that affects future responses - patterns that help the agent do the same job better next week than it did today Poor examples: - every message the system has ever seen - temporary details that stop mattering quickly - sensitive information with no clear reason to retain it - internal operational noise that makes future decisions harder instead of better The best memory is selective. It keeps the future useful, not just larger. --- ## A concrete example Imagine a delivery agent that helps a customer team roll out a product. Useful things to remember: - the customer prefers weekly written updates - the rollout is happening in three phases - the security review must be completed before production cutover Things that should not become durable memory: - every one-off scheduling discussion - transient debugging details from last Tuesday - sensitive details that were only needed for one narrow task Memory should preserve stable, high-value context, not random residue from past work. The retention model Think of memory as a filter between what the agent sees and what it should keep. Most information stays in the conversation history. Only a small, durable subset should become memory. [Diagram: Diagram showing conversation history being filtered into a small set of durable memory items with clear boundaries] --- ## Memory design guidelines A good memory setup is: - narrow enough that a human can explain it - durable enough to matter across conversations - aligned with the agent's actual job - reviewable if something goes wrong A simple test: a teammate should be able to read what the agent remembers and understand both *what* and *why* in a few sentences. From the CLI, the first operational inspection loop is: ```bash archagent list agentworkingmemory --agent archagent list agentworkingmemory --agent --search rollout ``` This is the fastest way to confirm whether a memory item is actually present before you blame the model or the thread. ArchAgents Portal mirrors the same view: open the agent in [ArchAgents Portal](/docs/operate-agents/portal) and look at the **Memory** tab on the agent detail page. Browse, search, and review what the agent currently retains in the same place you already review its routines and runs. --- ## The three questions that matter When deciding whether something belongs in memory, ask: 1. Will this still matter later? 2. Does retaining it make the agent meaningfully better at its job? 3. Would a human reviewer expect the agent to keep this? If the answer to any of those is unclear, the item does not belong in memory. --- ## Memory boundaries Memory persists across conversations, so it deserves the same attention you give any durable data store. Be intentional about what goes into memory: - personal data should only be retained when it serves the agent's job - confidential company information should follow your existing data handling policies - temporary task details belong in conversation history, not memory - if a reviewer would question why the agent kept something, it should not be in memory The platform gives you full visibility into what an agent remembers (`archagent list agentworkingmemory`), so you can audit and clean up at any time. Selective memory produces better agents. Agents with focused, relevant context are more predictable and more helpful than agents carrying everything they have ever seen. --- ## Good first uses of memory Strong early use cases include: - support agents remembering durable customer preferences - delivery agents remembering long-running project facts - internal operations agents remembering standing environment constraints Weak early use cases include: - broad "remember everything" experiments - retaining large amounts of thread content by default - storing information with no clear future decision value ## Memory in the operator workflow Memory becomes most useful when you pair it with the other operating surfaces: - use [Embed](/docs/operate-agents/embed) to inspect the agent's current local context - use `agentworkingmemory` to inspect what durable facts are present - use threads and messages to compare what the agent recently saw against what it still remembers That combination is how teams debug "why does this agent keep repeating the same assumption?" without turning the answer into prompt folklore. --- ## Practical rule Memory carries a clear reason for being there. If a value doesn't have one, leave it out. --- ### Notifications URL: https://latest.docs.archagents.com/docs/operate-agents/notifications Summary: Account, app, and agent updates that need your attention. Inbox view with filters and an archive. ## Overview The **Notifications** page at `/notifications` is the inbox for everything that wants your attention: org invitations accepted, agent runs that need approval, billing alerts, and security events on your account. [Diagram: Notifications page with filter chips for Active, Unread, Read, Archived, All, and a two-pane layout showing the inbox list and a detail panel] The notification bell in the bottom-left rail surfaces unread counts. Click through to the full page when you want to filter, archive, or read context-heavy items. --- ## Filters The header has four filter chips: | Filter | What it shows | |---|---| | **Active** (default) | Items that haven't been archived. Day-to-day view. | | **Unread** | Items you haven't opened yet. | | **Read** | Items you've opened but not archived. | | **Archived** | Items you've explicitly dismissed. | **Mark all read** in the header zeroes out the unread count without archiving. --- ## What shows up here The platform routes notifications to your inbox for things that have an actor (your account), a subject (an org, agent, network, or thread), and a verb that's worth surfacing later. Examples: - An org invite you sent was accepted. - An agent's routine is paused because a required credential expired. - A teammate joined your org. - Your 2FA enrollment lapsed and is being re-required by org policy. - A Solution you installed has a new version available. This is **not** the place for live agent activity, runs, or thread messages. Those go through the [Activity Feed](/docs/operate-agents/activity-feed) and the threads themselves. Notifications is the durable inbox; Activity is the live tape. --- ## Where to go next 1. [Activity Feed](/docs/operate-agents/activity-feed): the live feed of agent runs and routine events. 2. [ArchAgents Portal](/docs/operate-agents/portal): the dashboard the Notifications page lives on. 3. [Sign-in and Two-Factor](/docs/operate-agents/sign-in): account security settings that produce notifications. --- ### Activity Feed URL: https://latest.docs.archagents.com/docs/operate-agents/activity-feed Summary: A live record of what your agents and automations did, when they did it, and what came out of it. ## Overview The activity feed is the live, scrollable record of what your agents and automations are doing right now. Open it and you can see a routine fire, a workflow finish, a connector reconnect, all in the order they happened. Use it when you want to: - see what an agent did over the last hour, day, or week - find why a routine run failed and what it was working on - audit cross-org collaboration in a thread you participate in - watch a long-running automation execute - catch connector reauth events without polling integrations one by one It's the answer to "what just happened?" without opening a thread, a run, or a connector page first. --- ## What gets recorded | Kind | What it covers | |------|----------------| | `routine_run` | Each time an agent routine starts, completes, or fails | | `automation_run` | Each time an automation triggers, completes, or fails | | `generic` | Connector lifecycle events, audit events, and other notable activity | Every entry has a **level** so you can filter noise: | Level | Meaning | |-------|---------| | `debug` | Verbose detail useful when investigating a specific run | | `info` | Normal activity worth seeing in a feed | | `warn` | Something completed but with caveats, partial results, retries, soft errors | | `error` | Something failed and needs attention | | `audit` | Security-relevant events, sign-ins, role changes, connector reauth | Entries can carry **attachments**: files a routine produced, artifacts it published, scraped links, tasks, integration references. A feed entry carries enough context to act on by itself; you don't have to open every linked object. --- ## Reading the feed from the CLI ### List recent activity ```bash archagent list activity ``` Filter by agent, kind, level, or thread: ```bash archagent list activity --agent archagent list activity --kind routine_run --level error archagent list activity --thread ``` Page through older entries with the cursor returned in the previous response: ```bash archagent list activity --before-cursor ``` ### Inspect a single entry ```bash archagent describe activity ``` This shows the entry's title, content, the actor (agent or user), the linked routine run or automation run, attachments, and metadata. ### Stream live activity When you want to watch a routine or automation as it runs, attach to the live stream: ```bash archagent run activity --agent ``` Or watch every entry across an organization: ```bash archagent run activity --org ``` The stream stays open until you cancel with `Ctrl+C`. Each entry prints as soon as the platform records it. ### Delete an entry ```bash archagent delete activity ``` Use this to clean up noisy or test entries. Leave production audit entries in place. They're the trail you'll want when something goes wrong. --- ## Reviewing the feed in ArchAgents Portal The portal renders the activity feed at three scopes: - **Org-wide** at `/activity`: every entry across the organization. - **Per-agent** on each agent's **Activity** tab (`/agents/?tab=activity`): only entries for that agent. - **Per-network** on each network's **Activity** sub-rail (`/networks/`): entries scoped to that shared collaboration space. Each scope uses the same filter chips: [Diagram: Activity feed page with filter chips for Routine Runs, Automations, Thread Stories, Other, Debug, Info, Warn, Error, Audit, and All agents] The chips split into two rows: - **Kind**: Routine Runs, Automations, Thread Stories, Other. - **Level**: Debug, Info, Warn, Error, Audit. Plus an **All agents** dropdown to scope to a single agent without leaving the page. The left rail mirrors these as a sticky group when you want to keep filters visible while scrolling. Each entry expands inline to show its full content, attachments, and links to the routine run, thread, or session that produced it. The feed updates in real time; new entries appear at the top as they happen. --- ## Common patterns ### Triage failed routine runs ```bash archagent list activity --kind routine_run --level error archagent describe activity ``` The error entry contains the failure reason, the routine run ID, and the thread or session it was working on. Open the linked run for the full execution detail. ### Watch a scheduled automation execute If you have a daily report automation that should run at 9am, attach to the org stream just before: ```bash archagent run activity --org ``` You'll see the automation start entry, any intermediate routine runs it kicks off, and the completion entry, in the order they happen. ### Audit connector reauthentication Connector lifecycle events (`disconnected`, `token_refreshed`, `reauth_required`) appear as `generic` entries. Filter by level when you want to know what's broken: ```bash archagent list activity --level warn archagent list activity --level error ``` A `reauth_required` entry tells you which integration needs attention without having to inspect every connector individually. ### Cross-organization audit Activity feed entries respect organization and team boundaries. When organizations collaborate through a network (see [Network](/docs/collaborate/agent-network)), each side sees only the entries that belong to its own org or to the network, never another organization's private activity. --- ## Where the feed comes from You don't write to the feed directly. The platform writes entries automatically when: - a routine run starts, completes, or fails - an automation run starts, completes, or fails - a connector is connected, disconnected, refreshed, or needs reauthentication - a sign-in succeeds or fails (audit level) The titles and content come from the work the platform was doing, the routine name, the automation name, the connector that changed state. You shape what shows up in the feed by shaping the routines and automations themselves: clear names, focused responsibilities, and meaningful failure messages all surface here. --- ## Where to go next 1. [Portal](/docs/operate-agents/portal): review activity in the workbench. 2. [Automations](/docs/build-agents/automations): schedule the work that fills the feed. 3. [Agents](/docs/build-agents/agents): the routines whose runs become activity entries. 4. [Network](/docs/collaborate/agent-network): how cross-org activity stays scoped. --- ### Tasks URL: https://latest.docs.archagents.com/docs/operate-agents/tasks Summary: A shared work list for people and agents — create, assign, and track work with subtasks, blockers, comments, and a full history. ## Overview Tasks are the shared work list of ArchAgents. Every network has one, and every member of that network — human or agent — reads and writes the same list. An agent can file a task for work it can't finish in the cloud, a teammate can assign follow-up work to an agent, and you can watch all of it move from one place. Use tasks when you want to: - track work that outlives a single conversation - hand work between people and agents with a clear owner - break a deliverable into subtasks and order it with blockers - keep an auditable record of who changed what, and when A task is a real record, not a line in a chat message: it has a status, a priority, an optional owner and due date, comments, and an append-only history of every change. --- ## The task record | Field | What it holds | |-------|---------------| | Name, description | A short title, plus optional long-form notes (rendered as Markdown in the task view) | | Status | `open`, `in_progress`, or `done` | | Priority | `0` (urgent) to `4` (lowest); defaults to `2` (medium) | | Owner | The assignee — a user **or** an agent, never both; tasks can also be unassigned | | Due date | Optional ISO 8601 timestamp | | Tags | Labels for grouping and filtering, stored lowercase and de-duplicated | | Subtasks | Child tasks, nesting exactly one level | | Blockers | Other tasks that must finish first | | Comments | A discussion thread on the task | | Links, metadata | Named URLs and arbitrary key-value data your tools want to keep with the task | Statuses read like a checklist: a task starts `open`, someone (or some agent) claims it and moves it to `in_progress`, and marking it `done` stamps the completion time. Every task also records who created it and who owns it — with agents and people attributed distinctly, so you can always tell which changes came from automation. Tasks belong to a list. A network's list is shared by everyone in that network; your personal list holds tasks that are just yours. Tasks an agent creates during a thread conversation also attach to that thread, so the work items that came out of a discussion stay visible next to it. --- ## Working with tasks from the CLI Tasks require an org user session — sign in first with `archagent auth login `. The `--team` flag takes the team ID (`tem_...`) behind a network — the ID in the network's URL. Leave the scope flags off entirely and commands default to your personal list. ### List and search ```bash archagent list tasks --team archagent list tasks --team --status open --owner-agent archagent search tasks --team -q "billing" ``` List filters: `--status`, `--priority`, `--tag`, `--owner-user`, `--owner-agent`, `--parent ` (or `--parent none` for top-level tasks only), plus `--search` for substring matches on name, description, and tags. Page with `--limit` and `--after-cursor`. ### Inspect one task ```bash archagent describe task ``` This shows the full record: status, priority, owner, due date, tags, parent, and the subtask, blocker, and comment counts — including whether the task is currently blocked. ### Create and assign ```bash archagent create task --team \ -n "Rotate the staging API keys" \ --priority 1 \ --due-date 2026-08-01T17:00:00Z \ --owner-agent \ --tag security ``` Assignment is optional, and a task has one owner: a user or an agent. Reassign with `--owner-user` / `--owner-agent`, or pass `none` to unassign: ```bash archagent update task --owner-user archagent update task --owner-agent none ``` ### Move work along ```bash archagent update task --status in_progress archagent update task --status done ``` ### Subtasks Break a task down by creating children under it. Subtasks nest exactly one level, and a task that already has subtasks can't itself become one. ```bash archagent create task --team -n "Draft the runbook" --parent archagent list tasksubtasks archagent update task --parent none # promote back to top level ``` ### Blockers Order work by marking which tasks have to finish first: ```bash archagent update task --add-blocker archagent list taskblockers # what blocks this task archagent list taskblocking # what this task blocks archagent update task --remove-blocker ``` A task shows as **blocked** while at least one of its blockers is not yet done, and un-blocks automatically when the last open blocker completes. The flag is informational — it doesn't lock the task, so you can still change status when reality disagrees with the plan. Blockers must live on the same list as the task, and self-blocking or a direct cycle (two tasks blocking each other) is rejected. ### Comments and history ```bash archagent create taskcomment --task -b "Keys rotated; waiting on the deploy." archagent list taskcomments archagent list taskactivity ``` The activity history is an append-only feed of human-readable sentences — created, assigned, status changed, commented — with the actor and timestamp on each entry. It's the per-task answer to "who did what, when," and nothing can rewrite it. --- ## Agents on the task list Agents work the same list you do, through the `tasks` built-in tool. Toggle it on per agent from the agent's **Extensions** in the portal, or attach it from the CLI: ```bash archagent create agenttool --agent \ --kind builtin \ --builtin-tool-key tasks \ -k team-tasks ``` With the tool enabled, an agent can list, search, and fetch tasks, create and update them, look up valid assignees, post comments, and read a task's history. Two behaviors are worth knowing: - **Thread scoping.** In a thread conversation the tool defaults to that thread's tasks, so "add that to the list" lands on the right list without ceremony. The agent can widen to the whole team list when it needs to. - **Attribution.** When an agent acts inside a user's session, changes are recorded on behalf of that user; otherwise the agent acts as itself. Either way, the task's creator and history show exactly who did what. This is also how the `triage` routine preset works: an agent whose real work needs a local environment acknowledges the request in the thread, files the work on the thread's task list, and claims itself as owner — then completes the task when it next runs embedded. See [Concepts](/docs/start-here/concepts) for the preset model. --- ## Reviewing tasks in ArchAgents Portal **Network task list.** Each network has a **Tasks** tab: one shared list, sectioned by status. Sort by urgency, due date, or newest; filter by status, priority, tag, assignee, or overdue; and add a task inline with the quick-add row. Searching widens the view to include subtasks, which otherwise live under their parent. Every task is deep-linkable (`?task=tsk_...`), so you can paste a task straight into a chat message. **Task view.** Opening a task shows the full record: description, owner, tags, links, subtasks, blockers, the comment thread, and the activity history. You can edit fields, reassign, and work the subtask and blocker lists without leaving the overlay. **My Tasks.** The **My Tasks** page collects everything assigned to you across all your networks, so your day starts on one page instead of a tab-per-network crawl. **In-thread list.** On a network's chat tab, the inspector rail shows the live task list for the open thread — tasks agents file mid-conversation appear as they're created. --- ## Common patterns ### Hand cloud-found work to an embedded agent A triage agent spots a request it can't do from the cloud — a repo change, a test run. It files a task on the thread's list and claims it. You see the task appear in the thread rail, and the agent completes it the next time it runs embedded. Nothing gets lost between the conversation and the work. ### Gate a launch with blockers Create the launch task, then mark its prerequisites as blockers: ```bash archagent update task --add-blocker archagent update task --add-blocker ``` The launch task reads as blocked until the last prerequisite is done, and anyone — including an agent asked "can we ship?" — can check `list taskblockers` for what's left. ### Review an agent's workload ```bash archagent list tasks --team --owner-agent --status in_progress ``` Pair this with the task histories to see not just what an agent owns, but how it's been moving its work along. --- ## Where to go next 1. [Tools](/docs/build-agents/tools): the built-in tool catalog, including `tasks`. 2. [Concepts](/docs/start-here/concepts): the `triage` preset and how agents route hands-on work. 3. [Activity Feed](/docs/operate-agents/activity-feed): the org-wide record of agent activity, alongside each task's own history. 4. [Network](/docs/collaborate/agent-network): the shared space whose members and agents work the task list. --- ### Customer onboarding defaults URL: https://latest.docs.archagents.com/docs/operate-agents/customer-onboarding-defaults Summary: Reusable templates that decide what agent gets provisioned for each new customer onboarding, what the first message says, and who gets auto-added. ## Overview The default invite flow (Step 4 of the onboarder, or `/networks → Invite a customer`) attaches your FDA to every network you spin up with a customer. That covers the common case. **Customer onboarding templates** are the advanced version: reusable blueprints that drive a parallel launch flow when you want more than the default attach. Each template names which `AgentTemplate` to provision the customer-facing agent from, what its first message says, optionally an agent template to install on the customer's side, and which teammates to auto-add. Manage them at **Settings → Customer onboarding** (`/settings/admin/customer-onboarding`). [Diagram: Customer onboarding settings page showing the Configured templates section and an empty state encouraging the user to create the first blueprint] Each template is a [Custom Object](/docs/build-agents/custom-objects) instance with schema `customer-onboarding-template`. --- ## What a template configures The schema has these fields: | Field | Required | What it does | |---|---|---| | `template_key` | yes | Stable key for this template within your org. Use `"default"` for the first one. | | `name` | yes | Display name shown in settings. | | `status` | yes | `draft` or `active`. Only active templates can be used for new onboardings. | | `agent_template_config_id` | yes | Config ID of the `AgentTemplate` the customer's onboarding agent is provisioned from. | | `kickoff_message_template` | yes | The first message the newly created onboarding agent sends. | | `agent_name_template` | no | Display name for the provisioned agent (otherwise inherits from the template). | | `customer_side_agent_template_config_id` | no | An `AgentTemplate` config ID to install on the customer's side as well. | | `customer_side_agent_name_template` | no | Display name for the customer-side agent if one is provisioned. | | `auto_add_teammate_emails` | no | Provider-side teammate emails to resolve and auto-add to the network. | | `description` | no | Internal description shown in settings. | | `metadata` | no | Free-form key/value for UI or automation use. | --- ## Manage from the CLI Customer onboarding templates are custom objects, so the standard custom-object commands apply: ```bash archagent list custom-objects --schema-key customer-onboarding-template archagent describe custom-object ``` Create or update via a YAML file: ```yaml schema_key: customer-onboarding-template data: template_key: default name: Default customer onboarding status: active agent_template_config_id: kickoff_message_template: | Welcome! I'm here to help your team get set up. auto_add_teammate_emails: - alex@acme.example ``` Then `archagent deploy configs `. --- ## When templates apply Each new customer invite picks the active template marked `default` (or named explicitly in the invite if your invite flow supports it). Existing customer networks aren't retroactively changed when you edit a template; updates apply only to new onboardings that start after the change. --- ## Where to go next 1. [Network](/docs/collaborate/agent-network): what a customer network actually is. 2. [Agent Network - Getting Started](/docs/collaborate/agent-network-getting-started): the invite flow. 3. [Custom Objects](/docs/build-agents/custom-objects): the underlying schema and storage model. --- ### Sandboxes URL: https://latest.docs.archagents.com/docs/operate-agents/sandboxes Summary: Isolate test data from production so you can develop, test, and demo without affecting real users. ## Overview A sandbox is a separate copy of your project's runtime data. Same agents, same routines, same configs, but its own threads, users, messages, and credentials. Anything you do inside it stays inside it. You'll reach for one when you want to: - run a new routine against realistic data before it touches production conversations - give a customer-facing demo without polluting your live thread history - let different environments (staging, scratch, customer-specific) coexist without stepping on each other Every new project ships with a default sandbox called **Test**. Start there. --- ## A concrete example Imagine you are building a billing support agent. Before you let it touch production conversations, you can: 1. activate a sandbox 2. create a demo user 3. create a billing test thread 4. send a realistic message 5. inspect the result and any captured emails That gives you a safe way to answer the questions that matter: - does the agent respond correctly? - do the routines trigger when expected? - does the knowledge access look right? - do email and notification flows behave properly? The test-to-production boundary Treat a sandbox as the place where behavior becomes believable before it becomes real. The same setup patterns apply; only the data boundary changes. [Diagram: Annotated diagram showing test work staying inside a sandbox while production remains separate] --- ## Creating sandboxes Create additional sandboxes through the CLI or ArchAgents Portal: Slugs must be lowercase alphanumeric with hyphens, 2-100 characters, and unique per project. They cannot start or end with a hyphen. ```bash # CLI archagent create sandbox -n "Staging" -s staging ``` --- ## Access in sandboxes Each sandbox has its own access credentials, separate from production: - client-side work uses sandbox publishable keys - server-side setup uses sandbox secret keys - sandbox credentials only reach sandbox data, not production Create and revoke sandbox credentials through the CLI or ArchAgents Portal as needed for test environments and demos. If the work is test-only, use sandbox credentials so the resulting data stays in the sandbox. --- ## How sandboxes behave When you work inside a sandbox, the platform does four simple things: 1. It knows which sandbox you selected. 2. It keeps reads inside that sandbox automatically. 3. It saves new data back into that sandbox automatically. 4. It keeps that work separate from production and other sandboxes. Your code does not need a different logic path for sandbox versus production. The main difference is which sandbox or credential you choose. ```text Production credential → production workspace Sandbox credential → selected sandbox workspace ``` This separation applies across the main things teams care about, including users, teams, threads, messages, agents, configs, integrations, automations, files, and secrets. You do not need one mental model for testing and a different one for production. The main difference is which environment you selected. --- ## Sandbox emails Emails sent within a sandbox are captured instead of delivered. This lets you test email flows (registration, notifications, magic links) without sending real emails. ### Viewing captured emails ```bash # CLI archagent list sandboxmails --sandbox dsb_abc123 archagent describe sandboxmail sem_abc123 --sandbox dsb_abc123 ``` ### Cleaning up ```bash archagent delete sandboxmail sem_abc123 --sandbox dsb_abc123 archagent delete sandboxmails --sandbox dsb_abc123 --all ``` --- ## Using sandboxes with the CLI The CLI can be pointed at a sandbox so later commands operate on sandbox data: ```bash # Activate a sandbox archagent activate sandbox # List sandboxes, active sandbox is marked with * archagent list sandboxes ``` When a sandbox is active, later CLI commands create and inspect data inside that sandbox until you switch back. For day-to-day development, the common loop is: 1. activate the sandbox 2. create or update the agent 3. run a test thread 4. inspect the result 5. clean up or reset as needed --- ## ArchAgents Portal ArchAgents Portal at `https://archagents.com` provides a visual interface for sandbox management under **Project → Sandboxes**: - Create and manage sandboxes - Create the credentials each sandbox needs - Review recent usage and status - Revoke access with confirmation --- ## Design patterns ### Integration testing Use a sandbox to run automated tests without affecting production: 1. Create a sandbox (or use the default "Test" sandbox) 2. Use the sandbox publishable key in your test suite 3. Create users, agents, and threads, all isolated to the sandbox 4. Verify email flows by checking captured sandbox emails 5. Clean up by deleting sandbox emails between test runs This is the right pattern when you want realistic end-to-end testing without touching production. ### Demo environments Create a named sandbox (e.g., `demo`) with pre-seeded data for customer demos. Each demo sandbox is isolated, so you can reset it independently without touching production or other sandboxes. This works well when you want a stable environment for sales, solutions, or implementation walkthroughs. ### Staging pipeline Use sandboxes as lightweight staging environments: 1. `test` sandbox, automated test suite 2. `staging` sandbox, manual QA and review 3. Production, the main project workspace All three share the same project configuration but have completely separate user data, threads, and state. Exercise new agent behavior in `test` and `staging` first. Promote to production after the end-to-end behavior holds up against realistic data. --- ### Agents URL: https://latest.docs.archagents.com/docs/build-agents/agents Summary: Identity, routines, tools, and knowledge: the model behind everything. ## Overview An agent is a named AI worker with a job, the tools to do it, and the knowledge it needs. Your Forward Deployed Agent is one. The Onboarding Agent in your workspace is one. You'll build more. Concretely, an agent has: - A **name** people see ("Acme FDA," "Releases Helper"). - **Instructions** that say what it does and what it should not do. - **Tools** it can call during a session (search, knowledge lookup, open a PR, post in Slack, anything you've attached). - **Knowledge** it can look up (your runbooks, your repos, the websites you've connected). - **Memory** it carries between sessions. - **Routines** that fire when something happens in a thread. It is **not** a prompt or a single workflow run. An agent is a persistent identity. The same `Acme FDA` shows up in every customer network. The same routines fire every time a message lands in a thread that agent is on. The agent is the thing you manage; the runs are what it produces. --- Object Relationships Agent is the center of the model. Follow the arrows to see how the other pieces connect to it: An Agent has Routines (automations), Tools (capabilities), and a profile/instructions layer shown here as Identity Agents join Teams alongside Users, grouped under Organizations They communicate via Threads containing Messages They draw context from Sources (knowledge bases) connected through Installations Solid arrows = owns / contains · Dashed arrows = references / associates [Diagram: ArchAgents object relationship diagram] The core message flow is simple: 1. A person or system sends a message in a thread. 2. The platform checks whether any agent routines should react. 3. The agent uses its instructions, tools, and knowledge to decide what to do. 4. The agent replies, takes an action, or starts additional work. This is the flow you are building on top of. --- ## Creating an agent You already have agents in your workspace: the Forward Deployed Agent (auto-created on signup) and the Onboarding Agent. Most of the time you'll add new ones for internal jobs (monitoring, reporting, ops) rather than customer-facing work, which is what the FDA is for. Create one from the CLI: ```bash archagent create agent -n "Support Agent" -k support-agent \ -i "You help users resolve billing and support issues with short, concrete answers." ``` Flags: - `-n` (or `--name`): the display name people see. - `-k` (or `--lookup-key`): a stable handle your scripts and configs reference (`support-agent`, not the auto-generated ID). - `-i` (or `--instructions`): the system prompt that defines the agent's role. The agent persists in your workspace. From here, attach tools, knowledge, and routines, then deploy. --- ## Profile and instructions Every agent has profile details and instructions that shape how it shows up to other people. It defines things like: - display name - tone and voice - avatar or profile presentation - instructions that shape how the agent sounds in conversations You can think of this as the outward face of the agent. The agent is the same worker underneath; these settings shape how it appears and communicates. Update instructions, name, and profile details from the CLI or an agent template. In ArchAgents Portal, open **Agents** and click into an agent for a visual view you can review and edit. --- ## Routines Routines give the agent ongoing behavior. They answer two practical questions: 1. When should this agent act? 2. What should it do when that happens? For example, you can create a routine that runs when a new message appears: ```bash archagent create agentroutine --agent \ -n "billing-triage" \ -e thread.message_added \ -t script \ --script "{ route: \"billing\", priority: \"high\" }" archagent activate agentroutine ``` New routines start in `draft`, so save the routine ID from the create command and activate it when you want the handler to run. ### Common routine patterns - reply when a new message arrives - run on a schedule - react when a person joins a thread - respond when new knowledge or integration data becomes available ### Handler types | Handler type | When to use | What runs | |-------------|-------------|-----------| | `preset: participate` | Agent should join and respond in a thread conversation | Built-in conversation handler that posts the agent's response into the thread | | `preset: triage` | Agent mostly needs a local/embedded environment to do real work | Joins the conversation like `participate`, but acknowledges and tracks work on the thread task list (claiming itself as owner) instead of attempting it from the cloud | | `preset: send_message` | Agent should compose one message for a thread after an event or invocation | One-shot LLM session whose result is delivered to the target thread | | `preset: auto_memory_capture` | Extract and store key facts when a conversation ends (opt-in) | Built-in memory extraction | | `preset: do_task` | Scheduled, event-driven, or explicitly invoked work | Full LLM session with all agent tools; result stays on the run unless the invocation specifies delivery | | `script` | Deterministic logic (routing, filtering, transformations) | ArchAgents script expression | | `workflow_graph` | Multi-step process with branching or approvals | Workflow config | **`participate` vs. `do_task`** — pick based on where the result should go: - Use **`participate`** when the agent should reply inside a thread. The preset handles the thread-side mechanics and the user sees the agent's response as a thread message. - Use **`do_task`** for scheduled summaries, batch analysis, periodic audits, and explicit invocations. By default its result is inspected via `archagent list agentroutineruns` or the [activity feed](/docs/operate-agents/activity-feed). An explicit invocation can also request delivery to a message or thread. `do_task` is more powerful (full LLM reasoning with every tool attached). Use `participate` for live turn-by-turn conversation, or `send_message` when one event should produce one thread reply. **`triage` for embed-gated agents.** Some agents are only useful when running **embedded** — running locally as the agent, with access to a real environment (terminal, files, repository). In the cloud they can't clone a repo or run a test suite, so a `participate` routine would just produce replies it can't back up. Use `triage` instead: it joins the same `thread.session.join` session, but when a request needs hands-on local work it posts a brief acknowledgment and records the work as a **Task** — claiming itself as the owner — then completes it the next time it runs embedded. The `triage` routine is always given the `tasks` tool, even if the agent didn't enable it. Every agent's prompt also explains the per-message `agent_mode` attribute (`embedded`, `cli`, or absent for cloud) so agents can tell which work needs a local session. For a first agent, start with `participate` (so it responds in conversations) and `auto_memory_capture` (opt-in memory extraction — the agent creator adds this routine to enable it; it is not on by default). ### State Routines move through a few simple states: - **Draft** when you are still setting them up - **Active** when they should run - **Paused** when they should stop temporarily --- ## Tools Tools are how an agent does work instead of only talking about work. Some tools come from the platform, such as messaging, search, or computer-use capabilities. Others are custom tools you define for your own services. ### Built-in tools Use built-in tools when you want standard platform capabilities without having to build them yourself. ### Custom tools Use custom tools when the agent needs to call your own product logic, service endpoints, or company-specific actions. Read [Tools](/docs/build-agents/tools) for the real operator workflow: attach, inspect, activate, and run tools through an embed session. --- ## Knowledge Knowledge is the information the agent is allowed to use. That can include: - connected repositories and inboxes - uploaded files and documents - website content - thread history - long-term memory Access should be intentional. Give an agent only the knowledge it actually needs. ### Sources and installations There are two objects to understand here: - **Installation**: a connected external service, account, or integration - **Source**: a specific knowledge feed the agent can use from that installation That means: 1. connect a system or source 2. activate it for the agent 3. let the platform make that knowledge available when the agent needs it Read [Knowledge](/docs/build-agents/knowledge) for the operational model: integrations, sources, ingestions, items, and the debugging loop around them. --- ## Structured output By default, an agent responds with free-form text. When you need the response to fit a known shape — for downstream automation, for inter-agent handoffs, or for content policy enforcement — attach an `AgentMessageSchema` to the routine. The schema is a JSON Schema that constrains the agent's output. Required fields, enums, nested objects, and array shapes are all enforced before the response is accepted. You can also attach **field guards** to a schema to run content policies (regex, substring, or LLM-based) on each resolved field value. ```yaml routines: - name: customer-triage handler_type: preset preset_name: do_task preset_config: structured_message_template_refs: - "#/schemas/customer-summary" status: active ``` See [Structured Output](/docs/build-agents/structured-output) for the schema model and [Field Guards](/docs/build-agents/field-guards) for the content policy layer. --- ## Threads and messages Threads are where people and agents talk to each other. Messages are the individual events inside those threads. A person can send a message, an agent can respond, and routines can use those events to drive behavior. You can test that flow quickly from the CLI: ```bash archagent create thread -t "Billing support" --owner-type agent --owner-id archagent create user --system-user -n "Demo User" archagent create threadmember --thread --user archagent create threadmessage --thread --user \ -c "I need help with invoice INV-2041" ``` This creates the flow most developers care about: 1. a message arrives 2. the platform gathers the right context 3. the agent decides what to do 4. the agent replies, uses tools, or pulls in more knowledge ## Best practices 1. Give each agent a narrow, understandable job. 2. Add only the routines the agent really needs. 3. Give the agent only the tools and knowledge it should have. 4. Test new behavior in a sandbox before wider rollout. 5. Review agent behavior regularly and refine instructions, routines, and access as you learn what works. --- ## Deploy from a template The recommended workflow is to write an `agent.yaml` file (an AgentTemplate) and deploy it in one command: ```bash archagent deploy agent agent.yaml --name "Support Agent" ``` This creates the agent AND provisions all tools, routines, and installations in one command. ### Minimal AgentTemplate example ```yaml kind: AgentTemplate agent_key: support-agent name: Support Agent model: openrouter/anthropic/claude-sonnet-latest identity: | You help users resolve billing and support problems with short, concrete answers. Always ask one clarifying question before taking action. tools: - tool_type: builtin builtin_tool_key: search status: active - tool_type: builtin builtin_tool_key: knowledge_search status: active routines: - name: Reply to messages description: Respond when a new message arrives handler_type: preset preset_name: participate event_type: thread.session.join event_config: thread.session.join: filters: {} status: active installations: - install_type: memory/long-term config: {} ``` ### Key fields - **`identity`** -- system prompt and instructions that define the agent's behavior and boundaries. - **`model`** -- primary model for agent reasoning and replies. Start with `openrouter/anthropic/claude-sonnet-latest` unless you need a specific provider; accepted formats are `anthropic/`, `openai/`, `google/`, `xai/`, and `openrouter//`. - **`tools`** -- builtin or custom tools the agent can use. Builtin tools reference a `builtin_tool_key`; custom tools reference a handler and config. - **`routines`** -- event handlers that give the agent ongoing behavior. Each routine specifies a `handler_type` and an `event_type`. - `handler_type` values: `preset` (built-in behavior), `script` (custom logic), `workflow_graph` (multi-step workflows), `chain` (a linear sequence of preset / script / workflow_graph steps — see [Scripts → Chain-step input shape](/docs/build-agents/scripts#chain-step-input-shape) for how scripts inside chain steps read their input). - `preset_name` values: `participate` (join conversations), `triage` (join conversations but acknowledge and track work on the task list for agents that need a local/embedded environment), `send_message` (compose and deliver one message), `auto_memory_capture` (opt-in: extracts and stores key facts after sessions when enabled by the agent creator), `do_task` (execute instructions on an event, schedule, or explicit invocation). - `event_type` values: `thread.session.join`, `thread.session.leave`, `thread.message_added`, `schedule.cron`. - For cron routines, add `schedule: "0 9 * * 1"` (a cron expression in UTC) alongside `event_type: schedule.cron`. - **`installations`** -- connected capabilities such as memory, integrations, and knowledge sources. See [Installations](/docs/operate-agents/installations) for the full list of kinds. ### Validate before deploying ```bash archagent validate configs --kind AgentTemplate --file agent.yaml ``` Run this before `deploy` to catch schema errors early. --- ### Knowledge URL: https://latest.docs.archagents.com/docs/build-agents/knowledge Summary: What the agent can use, and how to prove it is working. ## Overview Knowledge is how an agent gets access to the information it should use when it works. That includes: - connected systems such as Google or GitHub - imported document collections - synced knowledge feeds - normalized items the platform can retrieve later It helps to think of knowledge as a pipeline, not a blob: - an integration connects to a provider - a source defines what knowledge feed to use - an ingestion syncs that feed - items are the normalized records the agent can actually draw from You can check each step: what is connected, what was synced, and what the agent can actually reach. The knowledge pipeline Knowledge becomes usable in stages: connect a system, define the source, sync it, then inspect the resulting items. [Diagram: Diagram showing a provider integration feeding a source, then an ingestion, then normalized knowledge items that an agent can use] --- ## A concrete example Imagine Company A runs the underlying deployment platform for Company B. Company A wants its `Platform Support Agent` to help Company B diagnose a failing integration, but only with approved material: - rollout runbooks - known retry issues - connector troubleshooting notes - past validated migration steps The right setup is not "give the agent every document." It is: 1. connect the approved provider or document collection 2. define the exact source that should be searchable 3. sync it 4. inspect what the platform actually ingested 5. let the agent use only that approved body of knowledge This keeps knowledge useful without turning it into "give the agent every document." --- ## The main pieces | Piece | What it means | |------|---------------| | **Integration** | The authenticated connection to a provider or workspace | | **Source** | The specific feed, collection, or scope of knowledge to sync | | **Ingestion** | The sync job that imports or refreshes knowledge | | **Item** | One normalized knowledge record the platform can retrieve later | | **Credential** | Secret material used for knowledge or browser access when needed | Two distinctions matter: - an **integration** says "we can connect to this system" - a **source** says "this is the specific knowledge stream we want from that system" This keeps the setup explainable to developers and security reviewers. --- ## Set up from the CLI Use the CLI or your coding agent to create knowledge connections: 1. connect the outside system 2. inspect scopes and ownership 3. confirm which workspace, repository, inbox, or document collection should be used For OAuth-based connections that require a browser redirect, the portal handles the initial authorization flow. Once connected, use the CLI to inspect and operate what was created. Review the result in the portal for a visual overview of connected systems and their status. --- ## Inspect integrations from the CLI List the connected knowledge integrations: ```bash archagent list integrations archagent describe integration ``` This tells you: - which provider is connected - which workspace it points at - who owns it - whether the connection is still healthy This is the loop for tracing exactly which knowledge connection the agent is using right now. --- ## Inspect and manage sources Sources are what developers work with most. They tell the platform which specific feed should become usable knowledge. ```bash archagent list knowledgesources archagent list knowledgesources --installation archagent describe knowledgesource ``` If you need to create or tune a source from the CLI: ```bash archagent create knowledgesource \ --type github_activity \ --team-id \ --payload '{"repository":"company-a/platform-rollouts"}' ``` A source type is provider-specific. `github_activity` is one concrete GitHub-backed source type. Teams create the first source from the CLI or an agent template, then use `describe knowledgesource` and `list knowledgesources` to inspect the exact shape before scripting more of them. The portal provides a visual overview of all sources and their status. A source is where the knowledge boundary becomes concrete. It is not just "GitHub is connected." It is "this exact repository or feed is part of the approved context." --- ## Check ingestion health Ingestion is where many real knowledge problems show up. If the agent is not seeing the knowledge you expected, check the ingestion state before assuming the model is wrong. ```bash archagent list knowledgeingestions archagent list knowledgeingestions --status failed archagent list knowledgeingestions --source archagent describe knowledgeingestion ``` This is the debugging loop: 1. inspect the source 2. inspect recent ingestions 3. confirm whether the sync succeeded 4. only then debug the agent behavior itself That sequence saves a lot of wasted prompt debugging. --- ## Inspect the resulting items Items are the normalized records the platform actually has available after ingestion. ```bash archagent list knowledgeitems --source archagent describe knowledgeitem ``` If an agent keeps missing a fact, this is where you verify whether that fact exists in the synced knowledge at all. This is a better debugging step than guessing about prompts. --- ## About credentials Some knowledge flows need credentials in addition to an integration. The CLI supports credential inspection and management: ```bash archagent list credentials archagent describe credential ``` These commands return credential metadata such as domain, owner, and last access time. They do not print raw secret values back to the terminal. Credential fields are stored encrypted at rest. The CLI is designed as a review and maintenance surface: it shows metadata, not raw secret values. For credentials that involve sensitive values, the portal provides a guided setup flow that keeps secrets out of shell history. The CLI is the primary surface for: - creating and managing credentials programmatically - inspection and auditing - controlled follow-up updates --- ## Knowledge in cross-company work Knowledge becomes much more important in Network scenarios. The rule is simple: - each company keeps its private knowledge private - collaboration happens in the shared thread - the shared thread does not imply shared private context This is both a configuration responsibility and a platform boundary: - only attach the sources an agent truly needs - review those sources before the agent joins shared work - do not assume a shared thread should widen an agent's retrieval scope Company B can ask Company A's agent for help without automatically widening access to Company A's full internal corpus. Use [Network](/docs/collaborate/agent-network) when the knowledge boundary needs to hold across company lines. --- ## Best practices Good knowledge setups follow five rules: 1. connect only the systems that help the agent do its actual job 2. keep each source narrow and intentional 3. inspect ingestion health before debugging model behavior 4. review items and ownership when results look wrong 5. avoid mixing company-private knowledge into shared collaboration spaces When the knowledge path is clear and explainable, the whole setup is easier to trust and review. --- ## Where to go next 1. Read [Agents](/docs/build-agents/agents) for the full runtime model. 2. Read [Installations](/docs/operate-agents/installations) for the broader attachment lifecycle. 3. Read [Tools](/docs/build-agents/tools) if the agent also needs to act, not just read. 4. Read [Network](/docs/collaborate/agent-network) for cross-company knowledge boundaries. --- ### Structured Output URL: https://latest.docs.archagents.com/docs/build-agents/structured-output Summary: Constrain agent responses to a JSON Schema and run policy checks on the result. ## Overview By default, an ArchAgents agent responds with free-form text. That's the right shape for conversation, support, and most chat-style interactions. When you need the agent to produce data (a triage decision, a customer summary, a structured action plan), you want the response to conform to a known shape every time. That's what an `AgentMessageSchema` does. It's a JSON Schema that tells the LLM exactly which fields to produce, with which types, and which are required. Use a structured message schema when: - the agent's output will be consumed by other code or systems - a downstream automation depends on specific fields being present - you want to enforce content policies on individual fields ([field guards](/docs/build-agents/field-guards)) - you want the response to be deterministic in shape, even if the values vary Schemas don't replace prompts, they constrain them. Your routine still tells the agent what to do; the schema tells the platform what shape to enforce on the result. --- ## A minimal example ```yaml kind: AgentMessageSchema id: customer-summary schema: type: object properties: summary: type: string sentiment: type: string enum: [positive, neutral, negative] next_action: type: string required: [summary, sentiment] ``` This config tells the platform: "When this schema is in effect, the agent must produce an object with at least `summary` and `sentiment` fields, where `sentiment` is one of three exact values." Save it as a config and deploy it like any other config: ```bash archagent describe configsamples agent_message_schema --to-file ./schemas/customer-summary.yaml # edit the file archagent validate configs -k agent_message_schema -f ./schemas/customer-summary.yaml archagent deploy configs ``` --- ## Linking a schema to a routine Reference the schema from an agent routine using `structured_message_template_refs`: ```yaml routines: - name: customer-triage handler_type: preset preset_name: do_task preset_config: instructions: | Read the customer's most recent message in the thread and summarize it. Decide the sentiment and propose the next action. structured_message_template_refs: - "#/schemas/customer-summary" status: active ``` When the routine runs, the agent generates a response that matches the schema. The platform validates the shape automatically and rejects malformed responses before they reach your other code. You can attach more than one schema to a routine when the agent has several response modes. The agent picks the schema appropriate to what it's doing, and the platform validates against that one. --- ## Schema references are portable strings `structured_message_template_refs` accepts lookup keys, virtual paths, or raw config IDs. It does not accept an inline schema object or a `ref!` object. Deploy the `AgentMessageSchema` config first, then reference it from the routine's `preset_config`: ```yaml routines: - name: ticket-triage handler_type: preset preset_name: do_task preset_config: structured_message_template_refs: - schemas/ticket-triage-output status: active ``` The CLI deploys dependency configs before provisioning the `AgentTemplate`, so the same portable ref works across environments without embedding a database ID in the template. --- ## Field guards Schemas don't only validate shape, they can also enforce content policies on the resolved field values. Add `field_guards` to a schema to require that fields pass content checks before the response is accepted: ```yaml kind: AgentMessageSchema id: customer-summary schema: type: object properties: summary: { type: string } sentiment: { type: string, enum: [positive, neutral, negative] } required: [summary, sentiment] field_guards: - kind: ContainsString fields: ["summary"] value: "CONFIDENTIAL" on_match: redact - kind: LLMJudge fields: ["summary"] prompt: > Does this summary mention any specific customer's full name or financial account number? on_match: reject ``` Guards can `reject` (block the response), `redact` (rewrite the field), or `warn` (record a violation but let it through). See [Field Guards](/docs/build-agents/field-guards) for the full guard catalogue and how to design good policies. --- ## What the schema controls A schema constrains the **shape** of the response, types, required fields, enums, nesting. It does not constrain the **content** unless you also attach field guards. The agent's instructions and tools still drive what the values mean; the schema makes sure those values arrive in a known structure. For free-form fields (a `string` summary, a `string` description), the LLM still generates whatever text fits the prompt. Pair the schema with field guards when content rules matter. --- ## Validation Validate schemas before deploying them: ```bash archagent validate configs -k agent_message_schema -f ./schemas/customer-summary.yaml ``` The validator checks: - the schema is a valid JSON Schema - all referenced field paths in any attached field guards exist - guard configs are valid for their kind The portal also validates schemas when you save them through the visual editor. --- ## Best practices 1. **Make the schema as tight as the work requires.** A schema with five required fields is easier to consume than one with twenty optional ones. 2. **Use enums for categorical fields.** `priority: low | medium | high` is much more useful than `priority: string` with conventions in the prompt. 3. **Pair structured output with field guards** when the response will be shared with humans or external systems. The schema enforces shape; guards enforce content. 4. **Reuse schemas across routines** when the same response shape applies in more than one place. Deploy once, reference by ID. 5. **Test schemas with real prompts.** Run the routine in a sandbox and inspect the resulting messages to confirm the agent is producing useful values, not just the right shape. --- ## Where to go next 1. [Field Guards](/docs/build-agents/field-guards): content policies that run on schema fields. 2. [Agents](/docs/build-agents/agents): how routines reference schemas. 3. [Activity Feed](/docs/operate-agents/activity-feed): where validation failures and guard violations are recorded. 4. [Configs](/docs/build-agents/configs): the file-backed deploy workflow for schemas. --- ### Workflows URL: https://latest.docs.archagents.com/docs/build-agents/workflows Summary: Design multi-step flows for approvals, handoffs, branching, and longer-running work. ## Overview A workflow is a multi-step process you can call from a routine, an automation, or a script. Each step is a node; nodes can branch, retry, wait for approval, or hand off to other workflows. Use one when "do X" turns into "do X, then if Y, do Z, then ask a human." The split with routines: - A **routine** decides *when* the work happens. - A **workflow** describes *how* it happens, step by step. Good fits for a workflow: - conditional branching ("if amount > $500, route to manager") - approvals ("wait for a human reply before continuing") - retries with backoff - longer business processes that need to survive restarts - handoffs between agents or between agents and people --- ## A concrete example Imagine a support agent that handles refund requests. The routine might react when a new message looks like a refund issue. The workflow could then: 1. classify the request 2. check account details 3. ask for human approval if the amount is large 4. send the final response 5. write the outcome back to the thread - the routine notices the moment - the workflow runs the process The workflow shape Use a workflow when the work needs to stay visible as a process: multiple steps, decisions, approvals, or handoffs. [Diagram: Diagram showing a workflow moving from trigger to classify to approval to action to write back] --- ## Building a workflow ### File-backed workflow configs Use the CLI or your coding agent to create and manage workflows as config-backed files: ```bash archagent list configkinds archagent describe configsamples workflow --to-file ./tmp/workflow.sample.yaml archagent validate configs -k workflow -f ./tmp/workflow.sample.yaml ``` After you have a workflow shape you want to keep: ```bash archagent sync configs archagent deploy configs ``` This is the primary path for workflows. They belong in source control where your team can review and iterate on them. When you save a workflow, the platform runs **semantic validation** in addition to schema validation. It checks that node references resolve, that data flowing between nodes has compatible shapes, and that conditional branches reach a terminal node. Errors are surfaced before the workflow is allowed to deploy, so broken graphs don't reach the runtime. ### Portal editor ArchAgents Portal also provides a visual workflow builder for reviewing and editing workflows: 1. Open **Workflows** in the portal. 2. Click **New Workflow** and enter a name. 3. Add nodes to the canvas. 4. Connect nodes to define execution order. 5. Save and test the flow. The editor includes: - **Run as User** selector so you can choose who the workflow runs as - **Debug mode** for inspecting workflow inputs and outputs - **Auto-versioning** for safe iteration and rollback Use the portal editor when you want a visual overview of the flow or need to quickly test whether a sequence makes sense. ### Workflow execution Workflows can be triggered three ways: 1. **Agent routines**: attach a workflow to an agent behavior 2. **Automations**: run a workflow on a schedule or important event 3. **Direct run**: test a workflow from the portal while you build it When a workflow starts, it receives the data from whatever triggered it. That makes workflows reusable. You can test one from the CLI or portal, then attach it to a routine or automation once the flow is clear. --- ## Node types Workflows are built from nodes. Each node does one job in the flow. | Node | What it does | |------|-------------| | **ScriptNode** | Run an ArchAgents script for custom logic or data transformation | | **HttpNode** | Make an HTTP request to an external API | | **ChatCompletionNode** | Call an LLM to generate text or make a decision | | **SwitchNode** | Branch the flow based on a condition | | **LoopNode** | Iterate over items and run a subflow for each | | **DelayNode** | Wait for a specified duration before continuing | | **EmailNode** | Send an email | | **WebhookNode** | Wait for an incoming webhook callback | | **TemplateNode** | Render a Liquid template into structured output | | **DataNode** | Transform or reshape data between steps | | **EntryNode** | The starting point of the workflow | Most workflows use a small subset of these. A typical flow might be: EntryNode -> HttpNode -> ScriptNode -> SwitchNode -> EmailNode. Workflow configs are YAML files. Use `archagent describe configsamples workflow` to see the full structure. The portal editor provides a visual view for reviewing and editing workflows. --- ## Scripts and expressions inside workflows Workflows support three ways to compute a value at a node input: - **Scripts** for custom logic and multi-step data handling - **Expressions** for simple conditions and field access - **Dynamic fields** for inline `{{expression}}` interpolation in otherwise-static values This gives you a practical mix: visual structure for the overall flow, and code only where it adds real value. Aim for workflows where the high-level process stays visible and code shows up only where it earns its place. ### Dynamic fields A dynamic field is a static value with `{{expression}}` placeholders that get evaluated at runtime. Use it when you want a literal-shaped input (a string, a URL, a header value) that needs to interpolate one or two pieces of upstream data without writing a script node. ```yaml url: "https://api.example.com/orders/{{ steps.parse_input.order_id }}" headers: Authorization: "Bearer {{ env.API_TOKEN }}" ``` The portal property panel exposes dynamic fields as a value kind alongside literal, expression, and script. Reach for dynamic when you need string concatenation or simple substitution; use expression when you need a single typed value; use script when the logic needs more than one step. ### Attaching a workflow to an agent routine Once the workflow exists as a config, a routine can point at it by config id: ```bash archagent update agentroutine \ --handler-type workflow_graph \ --config-id ``` That split is the part many teams miss: - the workflow holds the process definition - the routine decides when that process should run A workflow can also be a single step inside a chain routine (`handler_type: chain`). When it runs as a chain step, its input is wrapped as `{trigger: , inputs: {: ,...}}`, so ScriptNodes inside the workflow address the trigger via `$.trigger.` and upstream chain-step outputs via `$.inputs.`. Workflows run directly from a routine (not as a chain step) see the raw event payload at `$` as usual. See [Scripts → Chain-step input shape](/docs/build-agents/scripts#chain-step-input-shape). --- ## When to use workflows vs routines | Scenario | Use | |----------|-----| | Single event → single action | Routine | | Multi-step orchestration | Workflow | | Conditional branching | Workflow | | Data transformation pipeline | Workflow | | Scheduled batch processing | Automation → workflow | | Human approval gate | Workflow | Routines decide **when** work should run. Workflows define **what** should happen once execution begins. If you are unsure which one you need, ask the simpler question: - "Do I just need the agent to react?" Use a routine. - "Do I need a visible process with several steps?" Use a workflow. --- ## Debugging workflow runs When a workflow fails, the run record carries structured diagnostics that point at the exact node and operation that broke. Use the CLI to inspect: ```bash archagent list automationruns --automation --status failed archagent describe automationrun ``` Each failed step in the run reports: - the node that failed - the operation it was performing - the original error message from the script, HTTP call, or LLM provider - the input shape the node received Script failures inside `ScriptNode` propagate the underlying script error rather than collapsing it into a generic "node failed" message. That makes it possible to fix a workflow without re-running it locally to reproduce the issue. The same diagnostics show up in the [activity feed](/docs/operate-agents/activity-feed) for each routine or automation run that touched the workflow. --- ## Where to go next 1. Use `archagent describe configsamples workflow` to see the full YAML structure. 2. Read [Scripts](/docs/build-agents/scripts) for the custom logic you can embed inside workflow nodes. 3. Read [Automations](/docs/build-agents/automations) for scheduled and event-triggered workflows. 4. Read [Agents](/docs/build-agents/agents) for how routines connect workflows to agent behavior. 5. Read [Activity Feed](/docs/operate-agents/activity-feed) for inspecting workflow runs. --- ### Integrations URL: https://latest.docs.archagents.com/docs/integrations/overview Summary: Choose how agents connect to outside services, understand who owns each credential, and verify a connection before relying on it. > **Documentation status: Beta.** This section is actively being expanded and > refined. Page structure, terminology, and setup instructions may change as we > validate the integration workflows with more organizations. ## Overview Integrations connect an agent to a system outside ArchAgents. They provide the credential and provider-specific capabilities the agent needs to read data, take actions, or receive events. The word **integration** describes the external connection. An **installation** attaches that connection or another capability to a particular agent. Some integrations also have a third relationship, such as a Slack channel binding, that controls where the agent participates. ![Integration relationships from external service to agent installation and destination binding](/diagrams/integration-relationship-model.svg) ## The three questions to answer first Before connecting a service, decide: 1. **Whose identity should the agent use?** A person's account, or a shared app/bot identity? 2. **Who should be able to reuse the credential?** One agent, or several agents in the organization? 3. **Where should the agent operate?** Everywhere the credential allows, or only in selected repositories, channels, networks, or other destinations? Those answers determine the integration model. | Model | Credential owner | Agent attachment | Good fit | |---|---|---|---| | Personal OAuth | One person | `integration/*` installation | An agent should read and act as that person | | Shared app | Organization | `enablement/*` installation on each agent | Several agents should use one managed bot or app | | Destination binding | Organization or network | Provider-specific binding | An enabled agent should become the resident for one destination | > A shared app connection does not automatically make every agent a participant everywhere. The shared credential, agent enablement, and destination binding are separate controls. ## Supported integration families | Integration | Models | Documentation | |---|---|---| | Slack | Personal OAuth, shared Slack bot, channel and network bindings | [Slack](/docs/integrations/slack) | | GitHub | Personal OAuth, shared GitHub App | [Installations](/docs/operate-agents/installations#org-wide-integrations-configure-once-bind-per-agent) | | Gmail, Outlook, LinkedIn, X | Personal OAuth | [Installations](/docs/operate-agents/installations) | | MCP providers | OAuth, bearer token, API key, or provider-specific credentials | [Extensions & Integrations](/docs/more/extensions-integrations#mcp-servers) | The available providers and installation kinds can vary by workspace. Inspect the current server before automating setup: ```bash archagent list integrationproviders archagent list agentinstallationkinds ``` ## Shared integration workflow Shared Slack Bot and GitHub App connections use the same two-stage pattern: 1. An organization admin connects the provider once under **Settings → Integrations**. 2. Each agent that should use it receives the corresponding `enablement/*` installation. When exactly one matching shared integration exists, the enablement installation binds to it and activates automatically. If several matches exist, select one explicitly with `--shared-integration`. ```bash archagent list integrations --provider --auth-type app_installation --org archagent create agentinstallation \ --agent \ --kind enablement/ \ --shared-integration ``` Do not place a provider's external installation ID in the enablement configuration. `--shared-integration` expects the ArchAgents integration resource ID. ## Personal OAuth workflow Personal integrations belong to one agent and authorize through the person whose account the agent will use: ```bash archagent create agentinstallation \ --agent \ --kind integration/ archagent authorize agentinstallation archagent activate agentinstallation ``` The authorization command opens or returns the provider's OAuth handoff. The person completing that flow determines which external account the agent receives. ## Verify before use Treat a connection as ready only after its installation is active: ```bash archagent list agentinstallations --agent archagent describe agentinstallation -o json ``` Check these fields in the JSON response: | Field | What it tells you | |---|---| | `state` | Whether the installation is active, pending, or failed | | `next_action` | The setup step still required | | `shared_integration` | Which organization connection backs an enablement | | `error` | Why the latest setup or refresh failed | If an integration-backed tool is missing, inspect installation state before changing the agent's prompt or routines. ## Permissions and safety - Start with the smallest provider permissions that support the intended workflow. - Use a shared bot/app when the agent should have its own identity; do not borrow a human credential for convenience. - Attach shared integrations only to agents that need them. - Use destination bindings to limit where an enabled agent listens or replies. - Removing a shared integration can disable or remove every enablement backed by it. Review the affected agents first. - Re-run OAuth when a provider token expires or when new required scopes have been added. ## Next steps 1. Follow [Slack](/docs/integrations/slack) to install the Slack app, enable an agent, and place it in a channel or network. 2. Read [Installations](/docs/operate-agents/installations) for installation state, activation, and troubleshooting. 3. Read [Extensions & Integrations](/docs/more/extensions-integrations) when a built-in provider is not the right fit and you need MCP, webhooks, custom tools, or scripts. --- ### Slack URL: https://latest.docs.archagents.com/docs/integrations/slack Summary: Connect Slack to your organization, enable agents, assign channel residents, and understand how Slack channels and reply threads map into ArchAstro. > **Documentation status: Beta.** This guide reflects the current Slack > integration model, but its organization and setup instructions may change as > we validate the workflows with more organizations. ## Overview Slack has two credential models and one routing layer: | What you need | Use | Identity in Slack | |---|---|---| | One agent acts through one person's Slack account | `integration/slack` | The connected person | | Agents participate as the organization's Slack app | Org `slack_bot` integration plus `enablement/slack_bot` | The Slack bot, labeled as the replying agent when permitted | | One enabled agent owns a channel's incoming conversation | `SlackChannelBinding` | The channel's resident agent | Most team deployments should use the **shared Slack bot**. Use personal OAuth only when acting as a specific person is intentional. ![Slack integration model showing personal OAuth, the shared organization bot, agent enablement, and channel bindings](/diagrams/slack-integration-model.svg) ## Understand the four relationships Slack setup becomes much easier when each relationship has a distinct name: 1. **Slack workspace install** — an org admin authorizes the ArchAgents Slack app once. This creates the shared `slack_bot` integration and stores the bot credential. 2. **Agent enablement** — an `enablement/slack_bot` installation lets one agent use that shared bot connection. 3. **Channel binding** — a `SlackChannelBinding` makes one agent the resident for a channel, optionally binding that channel to a network. 4. **Mirror thread** — incoming Slack messages are represented in a thread in ArchAgents so the agent can reason and reply. Installing the workspace app does not by itself assign a resident to every channel. Likewise, a channel binding does not replace the agent's Slack enablement. ## Choose a tutorial | Goal | Start here | |---|---| | Let agents answer mentions and DMs as a bot | [Tutorial 1: install the shared Slack bot](#tutorial-1-install-the-shared-slack-bot) | | Let an agent read and act as one person | [Tutorial 2: connect personal Slack OAuth](#tutorial-2-connect-personal-slack-oauth) | | Make an agent the default resident in an internal channel | [Tutorial 3: assign an internal channel resident](#tutorial-3-assign-an-internal-channel-resident) | | Put an agent in a customer or Slack Connect channel | [Tutorial 4: bind a channel to a network](#tutorial-4-bind-a-channel-to-a-network) | | Add your agent while you are a guest in another company's workspace | [Guest-hosted channels](#guest-hosted-channels) | | Understand follow-ups in Slack reply threads | [Slack reply threads](#slack-reply-threads) | --- ## Tutorial 1: install the shared Slack bot Use this model when agents should participate under your organization's Slack app rather than impersonating a person. ### Before you begin You need: - ArchAgents organization-admin access - permission to install apps in the target Slack workspace, or a Slack admin who can approve the request - an existing agent - a channel where you can invite and test the bot For agents that respond to incoming conversations, the agent also needs: - a unique `lookup_key`, used as its addressable handle - an active `thread.session.join` participate routine ### Step 1: connect the workspace 1. Sign in to [archagents.com](https://archagents.com) as an organization admin. 2. Open **Settings → Integrations**. You can also complete **Onboarding → Set up Slack**. 3. On the Slack card, select **Enable**. 4. Choose the Slack workspace and approve the requested permissions. 5. Return to ArchAgents and confirm that Slack shows **Connected**. ![ArchAgents Slack setup page with the Enable button and an example agent conversation](/screenshots/onboard-slack.png) This is a one-time OAuth operation for the organization. It creates a shared integration with provider `slack_bot`; it does not create a separate bot token for every agent. ### Step 2: choose permissions The default installation requests the complete supported permission set. **Customize permissions** lets an administrator trim optional scopes before OAuth. | Capability | Slack scopes | |---|---| | Receive mentions and send replies | `app_mentions:read`, `chat:write` — required | | Use each agent's name and avatar on replies | `chat:write.customize` | | Read public channels | `channels:read`, `channels:history` | | Read private channels the bot has joined | `groups:read`, `groups:history` | | Create or manage private channels | `groups:write` | | Receive direct messages | `im:read`, `im:history` | | Read shared files | `files:read` | | Match Slack users to ArchAgents accounts | `users:read`, `users:read.email` | | Inspect the workspace | `team:read` | | Invite another workspace to a Slack Connect channel | `conversations.connect:write` | If you omit a permission, capabilities that require it remain unavailable. Reopen **Settings → Integrations** and select **Update permissions** when requirements change. ### Step 3: enable the agent Attach the agent to the organization's shared Slack bot: ```bash archagent create agentinstallation \ --agent \ --kind enablement/slack_bot ``` When exactly one Slack bot integration matches the agent's organization, the installation auto-binds and becomes active. If more than one matches, select the intended ArchAgents integration: ```bash archagent list integrations \ --provider slack_bot \ --auth-type app_installation \ --org archagent create agentinstallation \ --agent \ --kind enablement/slack_bot \ --shared-integration ``` `` is the ArchAgents integration resource ID. It is not the Slack workspace ID that starts with `T`. For config-managed agents, include the enablement in the `AgentTemplate`: ```yaml lookup_key: releases routines: - name: Participate in conversations event_type: thread.session.join handler_type: preset preset_name: participate status: active installations: - install_type: enablement/slack_bot config: {} ``` Deploying this template creates the same agent-level enablement. The participate routine is what lets the agent wake when it joins a mirrored conversation. ### Step 4: invite the app to a channel In Slack, open the target channel and invite the ArchAgents app. For example: ```text /invite @ArchAgent ``` Slack controls channel access. The bot cannot read private-channel history or post into a channel it has not joined, regardless of its ArchAgents installation state. ### Step 5: verify the installation ```bash archagent list agentinstallations --agent archagent describe agentinstallation -o json ``` Expected result: - kind is `enablement/slack_bot` - state is `active` - `shared_integration` identifies the org Slack bot connection - no `next_action` or setup error remains If the installation stays `pending` with `next_action: configure_shared_integration`, the shared workspace connection is missing, invisible to the current viewer, or ambiguous. ### Step 6: test the unbound routing path In a channel with no resident binding, try: ```text @ArchAgent @releases What shipped today? ``` The first mention addresses the Slack app. The second handle selects the agent by `lookup_key`. Without a recognized agent handle, the concierge handles the message. Also test a direct message to the app. If a DM or mention arrives but no reply is posted, use the [troubleshooting checklist](#troubleshooting). To make the agent the channel's default resident, continue to [Tutorial 3](#tutorial-3-assign-an-internal-channel-resident) for an internal channel or [Tutorial 4](#tutorial-4-bind-a-channel-to-a-network) for a customer-facing channel. --- ## Tutorial 2: connect personal Slack OAuth Use `integration/slack` when an agent should use one person's Slack access and act as that person. This connection is not the workspace bot and does not make the agent the receiver for `@ArchAgent` mentions. Typical uses include: - searching channels the connected person can access - importing that person's Slack activity as context - taking an explicitly authorized action through that person's account ### Step 1: create the personal installation ```bash archagent create agentinstallation \ --agent \ --kind integration/slack ``` Save the returned installation ID. ### Step 2: complete OAuth ```bash archagent authorize agentinstallation ``` Open the authorization URL and sign in as the person whose Slack identity the agent should use. Review the workspace and permissions before approving. ### Step 3: activate and verify ```bash archagent activate agentinstallation archagent describe agentinstallation ``` The installation should report `active`. If the token expires or Slack revokes access, authorize it again rather than replacing the agent. ### Personal OAuth versus the shared bot | Behavior | Personal `integration/slack` | Shared `enablement/slack_bot` | |---|---|---| | Credential belongs to | One Slack user | The organization Slack app | | Slack identity | The connected person | Bot, optionally customized with agent name/avatar | | Reusable by several agents | No | Yes, with one enablement per agent | | Receives app mentions and bot DMs | No | Yes | | Supports resident channel routing | No | Yes | | Good default for team agents | No | Yes | The two models can coexist on the same agent, but use that deliberately: tools and routines should make it clear whether an action uses the person's account or the bot. --- ## Tutorial 3: assign an internal channel resident A resident is the default agent for an internal Slack channel. Once assigned, ordinary incoming messages route to that agent; users do not need to include its handle every time. ### Step 1: list available agents From Slack, run: ```text /archagent ``` Select **Browse agents**, or use the agent's known `lookup_key` handle. ### Step 2: assign the resident Run this command in the channel the agent should own: ```text /archagent assign @releases ``` The command creates the internal channel binding when needed and makes the selected agent its sole resident. The change is announced in the channel so residency changes are not silent. For private channels, the person assigning the resident must be a channel member. The Slack app and resident agent still need the permissions and enablement described in Tutorial 1. ### Step 3: inspect or remove the resident ```text /archagent status /archagent remove ``` `remove` clears the resident but keeps the binding. The concierge resumes handling explicit app mentions. Use `/archagent unbind` when you intend to remove the channel binding itself. ### How internal routing works - A channel with a resident routes to that resident. - A channel without a resident falls back to the concierge and explicit agent handles. - Assigning a resident is channel-level; it is not scoped to one Slack reply thread. - A private channel remains governed by Slack membership and the synchronized mirror-thread membership. --- ## Tutorial 4: bind a channel to a network Use a network-bound channel for a customer relationship or Slack Connect channel. The binding does three jobs: - associates the Slack channel with the ArchAgents network - limits the channel to the selected resident agent - enrolls the selected agent in the underlying API `team`, which supplies the privacy boundary for mirrored messages Externally shared channels fail closed when they are not bound to a network. This prevents an unscoped concierge or arbitrary agent from answering across a company boundary. ### End-to-end Slack-native setup When the `/archagent` command is available, you do not need to copy the Slack workspace or channel ID. Slack includes both IDs in the command payload. From the target channel: 1. Invite the app: `/invite @ArchAgent`. 2. Run `/archagent` and confirm that the welcome screen opens. 3. For an internal channel, run `/archagent assign @`. 4. For a customer or externally shared channel, run `/archagent setup `, then complete the modal. Use `/archagent assign @` afterward if you need to change the provisioned resident. 5. Run `/archagent status` and confirm the expected network and resident. 6. Post `@ArchAgent Can you introduce yourself?` and confirm the resident replies. Management commands: ```text /archagent Open setup and agent discovery /archagent setup Acme Set up this customer channel /archagent status Show the binding and resident /archagent assign @releases /archagent remove Clear the resident; keep the binding /archagent unbind Remove the channel binding ``` ### Find the Slack workspace and channel IDs You need IDs only when using the portal form, CLI, API, or a custom workflow. To copy the channel ID in Slack desktop or web: 1. Open the target channel. 2. Select the channel name in the conversation header. 3. Open **About**. 4. Scroll to the bottom and select **Copy channel ID**. Channel IDs normally begin with `C`. The ID is stable even if someone renames the channel. Slack's API also returns channel names and IDs from [`conversations.list`](https://docs.slack.dev/reference/methods/conversations.list) when you need to look them up programmatically. ![Slack channel ID walkthrough showing the channel header, About tab, and Copy channel ID action](/diagrams/slack-find-channel-id.svg) The CLI's `--slack-team` value is Slack's workspace ID, historically named `team_id`; it normally begins with `T`. Read it from the connected org integration rather than guessing from the company name: ```bash archagent list integrations \ --provider slack_bot \ --auth-type app_installation \ -o json ``` Find the record for the target Slack workspace and copy its `installation_id`. That is the `` value used by `--slack-team`. The integration's ArchAgents resource `id` is a different identifier and must not be substituted. ### Option A: connect from the portal 1. Confirm the Slack app is connected under **Settings → Integrations**. 2. Open **Networks**, then select the customer network. 3. Open the **Connection** tab. 4. Under **Slack channels**, select **Connect Slack channel**. 5. Paste the Slack channel ID, optionally add a customer label, and select the resident agent. 6. Select **Connect**. The agent must already appear in the network. Add it under **Members** first if the agent list is empty. ### Option B: connect from the CLI ```bash archagent create slackchannelbinding \ --slack-team \ --channel \ --team \ --agent \ --customer-label "Acme" ``` In user-facing prose, `` is the network ID. The CLI and API retain the underlying `team` name. The command is an idempotent upsert. Repeat `--agent` only when a workflow intentionally permits several attached agents; the normal resident model uses one. Inspect the result: ```bash archagent list slackchannelbindings --team archagent describe slackchannelbinding \ --slack-team ``` Remove the binding: ```bash archagent delete slackchannelbinding \ --slack-team ``` Deleting a binding stops resident routing for that channel. It does not uninstall the organization Slack app or delete the agent's Slack enablement. ### Guest-hosted channels Being a guest in another company's Slack workspace gives your human account access to a channel. It does not give your organization's Slack app or agents access to that workspace. There are two supported topologies: | Channel topology | Slack app to use | |---|---| | The channel is hosted only in the other company's workspace | Install or approve your organization's Slack app in that host workspace | | The channel is shared to your workspace with Slack Connect | Use the Slack app installation on your side of the shared channel | For a channel hosted only in the other company's workspace: 1. Connect that workspace from your ArchAgents organization's **Settings → Integrations** flow. 2. Have a Slack administrator for the host workspace approve or complete the app installation if your guest account cannot install apps. 3. Ask a channel member to invite the Slack app to the channel. 4. Add `enablement/slack_bot` to the agent. 5. Bind the channel to a dedicated customer network and the agent, using the host workspace's `T…` ID and the channel's `C…` ID. ```bash archagent create slackchannelbinding \ --slack-team \ --channel \ --team \ --agent \ --customer-label "Customer name" ``` Use a network-bound customer binding for this topology. Do not use a bare internal-channel assignment merely because Slack considers the channel internal to the host workspace: people from another company can read the surface, so it needs the customer privacy boundary and guarded reply path. For Slack Connect, bind the installation that receives events on your side of the shared channel. The same Slack channel can have a separate installation and binding for each participating organization; one organization's binding does not grant credentials or agent access to the other. > If the host will not approve the Slack app and the channel is not shared into > your workspace with Slack Connect, you cannot add a resident agent to it. > Personal `integration/slack` OAuth can let an agent act through your user > account, but it does not install the bot, receive app mentions, or create > channel residency. ### Option C: set up a customer from Slack In the Slack Connect channel, run: ```text /archagent setup Acme ``` The setup modal can create the customer network and dedicated agent, bind the current channel, and record the customer relationship. Use these commands afterward: ```text /archagent status /archagent assign @customer-agent /archagent remove /archagent unbind ``` Use `assign` for changing the resident. Use `remove` to leave the network binding in place without a resident, and `unbind` to remove the channel-to-network relationship. --- ## Agent names and Slack identity One shared Slack app can represent many agents. The names serve different purposes: | Name | Example | Where it appears | How to change it | |---|---|---|---| | Slack app name | `ArchAgent` | App directory, DMs, and the outer `@ArchAgent` mention | Slack app configuration; changes the shared app for every agent | | Agent display name | `BigQuery Buddy` | Sender name on new replies and thinking indicators | Agent `name` | | Agent routing handle | `bigquery-buddy` | `/archagent assign @bigquery-buddy` and explicit agent addressing | Agent `lookup_key` | | Thread title | `#data-platform` | ArchAgents conversation list | Thread metadata; independent of the agent name | For a config-managed agent, set both the human-readable name and stable routing handle in its `AgentTemplate`: ```yaml kind: AgentTemplate name: BigQuery Buddy lookup_key: bigquery-buddy ``` Deploy the config through your normal config workflow. For a directly managed agent, update it from the CLI: ```bash archagent update agent \ --name "BigQuery Buddy" \ --lookup-key bigquery-buddy ``` Optionally update its Slack-facing avatar at the same time: ```bash archagent update agent \ --profile-picture ./bigquery-buddy.png ``` Slack displays the agent's name and avatar through per-message `username` and `icon_url` overrides. The organization Slack installation must include `chat:write.customize`; otherwise Slack falls back to the shared app identity. Grant it from **Settings → Integrations → Slack → Update permissions**. The change applies to new replies and new thinking indicators. Existing Slack messages keep the identity with which they were posted, and renaming the agent does not rename existing ArchAgents threads. After changing the handle, use the new value for assignment: ```text /archagent assign @bigquery-buddy /archagent status ``` --- ## Slack reply threads A Slack channel binding applies to the **channel**, not to one reply thread inside that channel. ![Slack channel routing diagram showing channel-level residency and reply placement using thread timestamp](/diagrams/slack-channel-routing.svg) When a person replies in a Slack thread: - Slack's `thread_ts` is preserved so the bot response is posted back into the same visible Slack thread. - The channel's resident still determines which agent receives the message. - The mirrored ArchAgents conversation is currently channel-level. Separate Slack reply threads in the same channel are not separate agent-context containers. This distinction matters for concurrent workflows. If two independent requests are active in different Slack reply threads, include a request identifier or other correlation data until per-reply-thread context isolation is enabled. There is no separate “install agent into this Slack reply thread” operation. Install the bot, enable the agent, then bind the channel or address the agent by handle. ## Routing reference | Channel state | Receiver | Handle behavior | |---|---|---| | Bound to a network | Network's resident agent | Resident wins; explicit handle does not reroute | | Bound to an internal resident | Internal resident agent | Resident wins; explicit handle does not reroute | | No resident binding | Named agent, otherwise concierge | `@handle` selects an enabled agent | Incoming Slack messages are mirrored into ArchAgents. The agent's participate routine produces a reply, and the Slack response forwarder posts it using the shared bot credential. Bot-originated echoes are suppressed to prevent reply loops. ## Proactive messages from scripts An agent with an active `enablement/slack_bot` can post from a script without managing a webhook URL or token: ```javascript let slack = import("slack") unwrap(slack.send({ channel: "#release-alerts", text: "Release 2.4 is ready for verification." })) ``` Reply inside an existing Slack thread by supplying `thread_ts`: ```javascript unwrap(slack.send({ channel: "C0123456789", thread_ts: input.thread_ts, text: "The rollback completed successfully." })) ``` The bot must be a member of the destination channel and have the necessary Slack scopes. ## Troubleshooting ### The agent installation is pending Run: ```bash archagent describe agentinstallation archagent list integrations --provider slack_bot --auth-type app_installation --org ``` - No shared integration: an org admin must complete the Slack install. - Several shared integrations: recreate or update the enablement with `--shared-integration `. - Integration is invisible: confirm the agent and integration belong to the same app and organization. ### Mentions arrive but the agent does not answer Check, in order: 1. The Slack app is invited to the channel. 2. The agent has an active `enablement/slack_bot` installation. 3. The agent has a unique `lookup_key` and active participate routine. 4. The deployed Slack reply workflow is present for the app. 5. The channel binding points to the expected resident. 6. The Slack install includes the scopes required for that channel type. ### The agent answers, but Slack receives nothing - Confirm `chat:write` is granted. - Confirm the app is still a member of the channel. - For customized agent identity, confirm `chat:write.customize` is granted. - Inspect the agent's Slack enablement; replies do not fall back to an unrelated org credential. ### A Slack Connect channel is rejected Externally shared channels require a network-bound `SlackChannelBinding` before a resident can be assigned. Use `/archagent setup ` where available, the network Connection UI, or `create slackchannelbinding`. ### A private channel cannot be changed Private-channel residency is member-managed. Ask a Slack member of that channel with the necessary ArchAgents permissions to perform the assignment. ### Users cannot see the mirrored conversation Slack and ArchAgents identities must be linked for personal visibility. The bot needs `users:read` and `users:read.email` for email matching, or the user can link their account from the Slack App Home tab where available. Slack membership remains the source of truth for private-channel visibility. ## Remove or rotate Slack access - Delete a channel binding to stop routing one channel. - Delete an agent's `enablement/slack_bot` to remove that agent's bot access. - Disconnect the org Slack integration only when you intend to affect every agent that uses it. - Reconnect or update permissions when rotating the workspace install; then verify each enablement returns to `active`. - Delete personal `integration/slack` installations individually when a person's access should no longer be used. ## Next steps 1. Read [Integrations](/docs/integrations/overview) for the shared-app and personal-OAuth models across providers. 2. Read [Installations](/docs/operate-agents/installations) for state and lifecycle details. 3. Read [Networks](/docs/collaborate/networks) for the user-facing network model behind the CLI's `team_id`. 4. Read [Scripts](/docs/build-agents/scripts) and the [Script language reference](/docs/build-agents/script-reference) to automate Slack actions. --- ### Automations URL: https://latest.docs.archagents.com/docs/build-agents/automations Summary: Run repeatable project-wide jobs on a schedule or when important events happen. ## Overview An automation is a job that belongs to your project, not to any one agent. It can run on a schedule (every morning at 8) or on an event (every time a thread is created), and it can call workflows, scripts, or other automations to do the actual work. Reach for one when: - the work needs to happen for the whole project, not for one agent identity - you want to react to an event in a single, reviewable place rather than scattering routines across agents - the job has a clock attached: daily digests, hourly retries, weekly backfills - you want to coordinate across agents, users, teams, or data sources Manage them from the CLI or ArchAgents Portal. --- ## A concrete example Imagine you want a daily activity summary for the whole project. That job does not belong to one support agent or one delivery agent. It belongs to the project itself. An automation can: 1. run every morning 2. gather the activity data you care about 3. call a workflow that formats the summary 4. send the result to the right thread or destination The main distinction: - routines shape one agent's behavior - automations run shared project-wide work The project-wide job model An automation sits above any one agent. It starts project work from a schedule or event and records the result. [Diagram: Diagram showing a schedule or event leading to an automation, then a workflow, then a result] --- ## Automation types ### Trigger automations Trigger automations run when a matching event happens. Examples: - someone joins a thread - a message is created - a connector is linked - an incoming email arrives These are useful when you want one shared reaction to an event without tying that reaction to a single agent. ### Scheduled automations Scheduled automations run on a timetable you define. Examples: - send a daily summary every morning - run a cleanup job every night - check for stuck work every hour These are useful when you want a heartbeat, cleanup, report, audit, or periodic sync. --- ## Available event types Inspect the full event list from the CLI or ArchAgents Portal. The most useful categories are: ### Thread events | Event | Description | |-------|-------------| | `thread.created` | A new thread was created | | `thread.message_added` | A message was added to a thread | | `thread.member_joined` | A member joined a thread | | `thread.member_left` | A member left a thread | ### Connector events | Event | Description | |-------|-------------| | `connector.connected` | An OAuth connector was connected | ### Context events | Event | Description | |-------|-------------| | `context.ingestion.succeeded` | A context ingestion job completed | | `context.ingestion.failed` | A context ingestion job failed | ### Email events | Event | Description | |-------|-------------| | `email.received` | An inbound email was received | | `email.processed` | An email was processed | --- ## Status states Automations move through three simple states: | Status | Behavior | |--------|----------| | `draft` | Saved, but not running yet | | `running` | Active and ready to react | | `paused` | Temporarily stopped | That lifecycle is intentionally simple. You only need to know whether an automation is ready, active, or temporarily stopped. --- ## Automation runs Each time an automation runs, ArchAgents records what happened so you can review it later. That run history is what makes automations operationally usable. When background work misbehaves, you need to see what ran and why instead of treating it like invisible magic. ### Run statuses | Status | Meaning | |--------|---------| | `pending` | Queued, awaiting execution | | `running` | Work is in progress | | `completed` | Finished successfully | | `failed` | The run ended with an error | | `cancelled` | The run was cancelled | ### Viewing runs ```bash archagent list automationruns --automation aut_abc123 archagent list automationruns --automation aut_abc123 --status failed archagent describe automationrun atr_abc123 ``` ## Automations vs. routines Both automations and routines react to events, but they solve different problems: | | Automations | Routines | |---|---|---| | Scope | Whole project | One agent | | Best for | Shared jobs and scheduled work | Agent behavior | | Typical example | Daily digest or event pipeline | Replying to new messages | Use automations for shared background work. Use routines for how a specific agent behaves. Another quick way to choose: - if the work belongs to one named agent, start with a routine - if the work belongs to the project, start with an automation --- ## Agent routines with LLM execution (do_task) The `do_task` preset is the most capable routine type. It triggers a full LLM execution session where the agent can think and act using all of its configured tools. Use it when you want an agent to reason about a task on a schedule or in response to an event, not just run a deterministic script. ### Example: weekly report routine ```yaml routines: - name: weekly-report description: Generate weekly activity summary handler_type: preset preset_name: do_task preset_config: instructions: | Review all activity from the past week. Summarize key findings and send a Slack message to #reports. schedule: "0 9 * * 1" event_type: schedule.cron status: active ``` ### Key fields - **`preset_name: do_task`**: tells the platform to run a full agent session with LLM reasoning. - **`preset_config.instructions`**: the task the agent should perform. Write this like you would write a prompt. - **`schedule`**: a cron expression for when to run (e.g. `"0 9 * * 1"` means every Monday at 9 AM **UTC**. All schedules run in UTC, convert from your local timezone before writing the cron expression). - The agent gets access to **all its configured tools** during execution: search, knowledge, integrations, memory, and anything else you have wired up. ### do_task vs. script routines Script routines run deterministic code. They always do the same thing the same way. `do_task` routines run the LLM with full tool access. The agent reasons about the instructions, decides what tools to call, and adapts to whatever it finds. Use `do_task` when the work requires judgment, not just execution. ### Chain routines (multi-step, linear) When a single handler isn't enough and a full workflow graph is overkill, use `handler_type: chain`: a linear sequence of `preset` / `script` / `workflow_graph` steps, each one's output addressable by name by the next. Steps share an input envelope so downstream steps can read upstream outputs: ```yaml routines: - name: classify-then-notify handler_type: chain event_type: agentroutine.invoked steps: - name: classify handler_type: preset preset_name: do_task preset_config: instructions: "Classify the inbound message." - name: log handler_type: script script: | println($.inputs.classify.output) $.inputs.classify.output ``` Scripts and workflows **inside chain steps** receive a wrapped input shape: `{trigger: , inputs: {: ,...}}`. They address the trigger event via `$.trigger.` and upstream outputs via `$.inputs.`, not `$.` directly. Single-handler script routines are unaffected. See [Scripts → Chain-step input shape](/docs/build-agents/scripts#chain-step-input-shape) for details. ### Delivering an invoked routine's result An `agentroutine.invoked` call can attach a typed `delivery` destination. The platform persists this intent on the routine run and delivers the run's final text result once. For a chain routine, intermediate step outputs are never posted. Use a reply destination when the result should follow the origin of an inbound message, including a mirrored Slack thread: ```json { "message": "Handle this request", "delivery": {"type": "reply", "message": "msg_..."} } ``` Use a thread destination when there is no message to reply to: ```json { "message": "Post the weekly summary", "delivery": {"type": "thread", "thread": "thr_..."} } ``` The equivalent CLI flags are `--delivery-message msg_...` and `--delivery-thread thr_...`. They are mutually exclusive. Omit both (or pass `{"type":"none"}` through the API/SDK) to keep the result on the routine run without posting it to a conversation. --- ## CLI commands ```bash # List automations archagent list automations archagent list automations --type trigger # Create from a workflow config archagent create automation -n "Nightly Report" -t scheduled --schedule "0 0 * * *" --config-id cfg_abc123 # Create from an AutomationTemplate archagent create automation -n "Customer Digest" --template tmpl_digest # Run scheduled work as a specific user archagent create automation -n "Account Cleanup" -t scheduled --schedule "0 4 * * *" \ --config-id cfg_cleanup --run-as-user usr_abc123 # Manage state archagent activate automation aut_abc123 archagent pause automation aut_abc123 # Update archagent update automation aut_abc123 -n "Updated Name" --config-id cfg_def456 # Delete archagent delete automation aut_abc123 # View runs archagent list automationruns --automation aut_abc123 archagent describe automationrun atr_abc123 ``` ### Templates `--template ` creates the automation from an AutomationTemplate config: a reusable definition you can deploy across projects or environments. Templates are managed like other configs (`archagent describe configsamples automation_template`, `archagent deploy configs`). Use templates when you have an automation pattern you want to reproduce in more than one place. ### Run as By default, scheduled automations run with platform-level access scoped to the project. Pass `--run-as-user ` to bind the schedule to a specific user: every run uses that user's identity, which controls what knowledge sources, integrations, and team memberships the work can reach. This is useful when: - the daily report should only see what one operator can see - the cleanup job should only touch resources owned by a specific team member - the audit trail should attribute the activity to a real user Use it deliberately: a scheduled run keeps working long after you set it up, so the user identity should be one that will keep the access it needs. --- ## Design patterns ### Event-driven onboarding Trigger shared onboarding work when a new user joins a thread: ```bash archagent create automation -n "Onboarding Flow" \ -t trigger \ --trigger thread.member_joined \ --config-id cfg_onboarding_workflow ``` ### Scheduled reporting Run a daily job that gathers activity and posts a summary: ```bash archagent create automation -n "Daily Activity Report" \ -t scheduled \ --schedule "0 9 * * *" \ --config-id cfg_daily_activity ``` ### Context ingestion monitoring React to ingestion failures so a team can retry or investigate: ```bash archagent create automation -n "Ingestion Failure Alert" \ -t trigger \ --trigger context.ingestion.failed \ --config-id cfg_ingestion_alert ``` --- ### Scripts URL: https://latest.docs.archagents.com/docs/build-agents/scripts Summary: Write focused custom logic for workflows and routines, plus ScriptTest files that exercise scripts through the CLI and portal test runner. ## Overview Scripts are where you put the small pieces of custom logic that give a workflow or routine its project-specific behavior. They are useful when the platform already gives you the overall structure, but you still need code for the part that is unique to your business. Typical uses include: - reshaping data between steps - applying policy checks - adapting one system's format to another - making a routing decision that is too custom for a simple expression A script is a small, reviewable piece of logic inside an otherwise declarative flow, not a place to write arbitrary code. --- ## Language basics The ArchAgents script language is expression-oriented. The last expression in the script body is the return value -- there is no `return` keyword. Key syntax rules: - **Variables**: `let x = 10` (no `const`, `var`, or `function` keywords) - **Anonymous functions**: `fn(x) { x * 2 }` - **Imports**: `import("array")`, `import("requests")`, etc. - **Input payload**: `$` gives access to the input data via JSONPath - **Input declarations**: `input var_name` declares variables from the execution environment (for workflow step outputs) - **Environment variables**: `env.API_KEY`, `env.SLACK_WEBHOOK`, must be set at the organization level first (see [Setting env vars for your scripts](#setting-env-vars-for-your-scripts)) - **Comments**: `//` single-line and `/* */` multi-line - **Semicolons**: optional (automatic semicolon insertion) - **No loops**: use `array.map`, `array.filter`, `array.reduce` instead of `for` or `while` Available import namespaces: `requests`, `array`, `string`, `map`, `datetime`, `math`, `result`, `email`, `jwt`, `slack`, plus app-specific namespaces like `agents`, `threads`, `users`. See the [Script Language Reference](/docs/build-agents/script-reference) for the full list of namespaces, functions, and signatures. --- ## Gradual typing Scripts support optional type annotations. You can write loose, untyped code while you're prototyping, and add types where you want stronger guarantees, at function boundaries, on workflow inputs, or on object shapes you pass between steps. ``` // Annotate a function with parameter and return types let parse_amount = fn(value: string): number { string.toNumber(value) || 0 } // Annotate the input payload shape input $: { order_id: string, items: array } // Annotate a local with an object shape let summary: { total: number, count: number } = { total: 0, count: array.length($.items) } ``` When you annotate a value, the script engine uses **bidirectional inference**: it propagates the type into expressions that depend on it, narrows types inside conditionals, and reports a structured error when an operation doesn't fit. Type-checking happens at validation time: - `archagent validate configs -k script -f ./script.yaml` reports type mismatches alongside syntax errors - the portal script editor surfaces type diagnostics as you type - typed function boundaries also enforce types at runtime, so a typed parameter that receives the wrong shape fails fast instead of silently producing wrong output You can also use **interfaces** to define a structural shape once and reuse it: ``` interface Order { id: string items: array total: number } let total_for = fn(order: Order): number { order.total } ``` Typing is gradual on purpose: untyped code keeps working, and you can add annotations to the parts that matter without rewriting everything else. The type system is documented in full in the [Script Language Reference](/docs/build-agents/script-reference). --- ## A concrete example Imagine a workflow that processes refund requests. Most of the workflow stays visual -- receive the request, gather account info, check approval, send the result. The script handles the custom part in the middle: calculate the refund, normalize billing data, enforce a business rule. ``` let http = import("requests") let arr = import("array") let items = $.order.line_items let eligible = arr.filter(items, fn(item) { item.refundable == true }) let totals = arr.map(eligible, fn(item) { { sku: item.sku, refund_amount: item.price * item.quantity } }) let grand_total = arr.reduce(totals, 0, fn(acc, t) { acc + t.refund_amount }) let approval = unwrap(http.post(env.BILLING_API_URL, { headers: { "Authorization": "Bearer " + env.BILLING_API_KEY }, body: { order_id: $.order.id, amount: grand_total } })) { eligible_items: totals, total_refund: grand_total, approval_id: approval.body.id } ``` That script reads the input payload with `$`, filters and transforms data with `array` functions, calls an external API with `requests`, and returns a structured object for the next workflow step. --- ## Execution contexts Where a script runs determines what `$` contains and what capabilities are available. | Context | `$` contains | `env` available | Builtin tools available | |---------|-------------|-----------------|------------------------| | Workflow ScriptNode | Step input data | Yes | No | | Routine handler (script type, single-handler) | Event payload | Yes | No | | **Chain routine step (script or workflow)** | **`{trigger: event, inputs: {step_name: output, …}}`** | **Yes** | **No** | | Custom tool script | Tool arguments | Yes | No | | `do_task` preset | N/A (LLM has full tool access) | Yes | Yes (all agent tools) | Scripts run under the same scoped platform authorization model as the routine or workflow that invoked them. Scripts can also use `input var_name` to declare named variables from the execution environment. This is useful when a workflow step outputs a named result that the next script needs to consume. Unknown identifiers are errors; declare them with `let` or `input`. ### Chain-step input shape When a script runs **inside a step of a chain routine** (`handler_type: chain`), it does not see the raw event at `$`. The platform wraps the input so each step can read both the original trigger and any upstream step's output by name: ``` { "trigger": , "inputs": { "": ,... } } ``` So a chain-step script addresses the trigger event via `$.trigger.` and upstream outputs via `$.inputs.`. Scripts that run inside a `workflow_graph` step see the same wrapped shape: the workflow's internal ScriptNodes address `$.trigger` and `$.inputs.` the same way. Only chain-step scripts are wrapped; single-handler script routines continue to see the raw event payload at `$`. Unnamed steps' outputs are still written to the run's metadata but aren't addressable by name from downstream steps. Give every step you want to reference a unique `name`. ### Custom-tool scripts: the calling thread When a script is the handler for a custom tool, the tool's argument map lives at `$` as usual. The script can also read the thread the tool was invoked from with `threads.current()`: ``` let threads = import("threads") let thread = unwrap(threads.current()) let channelId = thread.metadata.slack_source.channel_id ``` This is the right path when the value the tool needs lives in thread metadata rather than in the tool's arguments. For example: the Slack channel that owns the conversation, the GitHub repo the thread is scoped to, or any other context the LLM shouldn't have to copy by hand. Use `threads.current()` instead of asking the LLM to fill those values into the tool's argument schema. --- ## Scripts vs expressions | Feature | Script | Expression | |---------|--------|------------| | Multi-step logic | Yes | No | | Return value | Last expression (implicit) | Implicit evaluation | | Imports | Yes (`import("namespace")`) | No | | HTTP calls | Yes (via `requests`) | No | | Error handling | `unwrap()` builtin, `result` namespace | Minimal | | Use in workflows | Full ScriptNode | Inline conditions and field access | | Best for | Custom behavior, transformations | Small checks, field access, routing guards | Use expressions when the logic is tiny and obvious -- a field comparison, a null check, simple string interpolation. Use scripts when: - the code needs several steps or intermediate variables - you need to call an external service - the logic needs to be tested on its own - the transformation is central enough that it deserves a named, reusable unit --- ## Common patterns ### HTTP call with error handling ``` let http = import("requests") let response = http.get(env.STATUS_API_URL, { headers: { "Authorization": "Bearer " + env.API_TOKEN } }) let body = unwrap(response, { status: "unknown" }) { service_status: body.status } ``` ### Conditional notification ``` let mail = import("email") let amount = $.invoice.total let recipient = if (amount > 10000) { env.ALERTS_EMAIL } else { env.INFO_EMAIL } unwrap(mail.send({ to: recipient, subject: "Invoice " + $.invoice.id, text_body: "Amount: $" + string.toString(amount) })) { notified: true, to: recipient } ``` ### Data pipeline ``` let arr = import("array") let str = import("string") let raw = $.records let cleaned = arr.filter(raw, fn(r) { r.email != null }) let normalized = arr.map(cleaned, fn(r) { { email: str.lowercase(r.email), name: str.trim(r.name), source: "import" } }) let by_domain = arr.reduce(normalized, {}, fn(acc, r) { let domain = str.split(r.email, "@").1 let existing = map.get(acc, domain, []) map.put(acc, domain, arr.concat(existing, [r])) }) { processed: arr.length(normalized), by_domain: by_domain } ``` --- ## Setting env vars for your scripts Scripts reference environment values with `env.VAR_NAME`, for API tokens, webhook URLs, or any configuration that shouldn't live in the script source. Those values are set at the **organization level** so every script, routine, and workflow in the org can read them. Create them with the CLI (every command requires `--org `): ```bash archagent create orgenvvar --org --key MY_API_KEY --value "sk-..." archagent create orgenvvar --org --key ALERTS_SLACK_WEBHOOK --value "https://hooks.slack.com/..." ``` List and manage existing ones: ```bash archagent list orgenvvars --org archagent describe orgenvvar --org archagent update orgenvvar --org --value "new-value" archagent delete orgenvvar --org ``` Once set, any script can read the value at runtime: ``` let http = import("requests") let resp = http.get("https://api.example.com/orders", { headers: { "Authorization": "Bearer " + env.MY_API_KEY } }) ``` A script that references `env.MY_API_KEY` passes validation whether or not the variable is set, the type checker treats `env.*` as a string. At runtime, an unconfigured variable returns an empty string. Set the env vars before deploying scripts that reference them so every call resolves to the expected value. --- ## Validation The CLI validates script syntax with `archagent validate configs`, and the portal also validates syntax when you save. Syntax errors (mismatched braces, unknown operators, malformed expressions) are caught at validation time. However, validation does **not** check runtime function availability. A script that calls a function that does not exist in the imported namespace will pass validation but fail at execution time. Always test scripts with sample input before deploying them in a live workflow. --- ## Writing and testing scripts Write scripts locally in your editor or coding agent, then deploy them as configs: 1. Generate a sample with `archagent describe configsamples script`. 2. Write the custom logic in your local file. 3. Validate with `archagent validate configs -k script -f ./path/to/script.yaml`. 4. Deploy with `archagent deploy configs`. Files ending in `.agentscript` or `.aascript` are also recognized by the deploy step, useful when you want to keep the script body in its own file rather than embedded inline in YAML. You can also validate and run scripts directly from the CLI: ```bash archagent validate scripts --file ./path/to/script.yaml archagent run scripts --file ./path/to/script.yaml --input '{"key": "value"}' archagent describe scriptdocs ``` `archagent describe scriptdocs` prints the full script language reference. The portal also provides a script editor and ScriptTest runner: 1. Open **Scripts** in the portal. 2. Use **New Script** for production scripts or **New Test** for `ScriptTest` files. 3. Run a script with sample input to verify behavior. 4. Open a test and use **Run Tests** to see pass/fail results and assertion markers. 5. Use version history for rollback if a later change is wrong. Good scripts are small enough to review quickly, narrow enough to explain in one sentence, easy to test with sample input, and focused on one job. When a script starts absorbing too much workflow logic, the visual process disappears and the workflow becomes a box of code -- a sign that the script should be split or the workflow restructured. --- ## Writing tests for a script A test is itself a script — `import("test")` gives you a Jest-style API for grouping cases, asserting on results, and mocking namespace calls. Test files live next to your production scripts and end in `.test.aascript`. ``` // add.test.aascript let test = import("test") let math = import("script:math-helpers") // the script you're testing test.describe("add", fn() { test.it("adds two positive numbers", fn() { test.expect(math.add(2, 3)).toEqual(5) }) test.it("treats null as zero", fn() { test.expect(math.add(null, 4)).toEqual(4) }) }) ``` ### Available API The `test` namespace exposes: - `test.describe(name, fn())` — groups one or more `it` cases under a named suite. Nestable; the test report shows the full path (`outer > inner`). - `test.it(name, fn())` — declares a single test case. A test passes when every `expect(...)` inside it passes and the body does not raise a runtime error. An `it` with **no** assertions is reported as a failure — call `expect` at least once. - `test.beforeEach(fn())` / `test.afterEach(fn())` — hooks that run around every `it` in the enclosing `describe` (and nested describes). Outer hooks run before inner hooks. `afterEach` still runs when the test body errors, so it's safe to use for teardown. - `test.expect(actual).(...)` — record an assertion. Matchers: - `.toEqual(expected)` — structural equality (`==`) - `.toBe(expected)` — strict identity (`===`) - `.toBeOk()` — value is a `Result.ok` - `.toBeError()` — value is a `Result.err` - `.toContain(item)` — list contains item, or string contains substring - `.toMatch(pattern)` — string matches a regex - `.toHaveLength(n)` — list / string / map has `n` elements Matchers never raise — a failed match records a failing assertion entry and the rest of the `it` keeps running so you see every failure, not just the first. ### Mocking external calls Use `test.mock` inside an `it` to swap out a namespace method for that one test. The mock is auto-removed when the `it` returns, so the next case sees the real implementation again. Use `test.spy` to record what a method was called with (combine with `test.mock` first if you also want to replace the implementation). ``` test.describe("notify", fn() { test.it("posts a single slack message per alert", fn() { test.mock("slack.send", fn(args) { result.ok({ok: true}) }) let s = test.spy("slack.send") let mod = import("script:notify") mod.run({alerts: [{level: "high"}]}) test.expect(s.calls()).toHaveLength(1) }) }) ``` Side-effecting namespaces (`requests`, `slack`, `email`, `storage`, etc.) are **not** auto-mocked — if you want a test isolated from the real network or DB, mock the methods it calls explicitly. ### Rebinding input `test.withInput({...}, fn())` runs a body with `$` rebound. Handy when one `it` block needs to exercise a script under several input shapes without splitting into separate tests: ``` test.it("handles both string and number ids", fn() { let mod = import("script:resolve-id") test.withInput({id: "abc"}, fn() { test.expect(mod.default).toEqual("abc") }) test.withInput({id: 42}, fn() { test.expect(mod.default).toEqual(42) }) }) ``` ### File layout - Production scripts: `*.aascript` (or `*.agentscript`) — deploy as `kind: Script`. - Test scripts: `*.test.aascript` — deploy as `kind: ScriptTest`. Both file types are recognized by the deploy step; the compound `.test.aascript` extension routes to the `ScriptTest` config kind so tests are listed and run separately from production scripts. Test scripts run with `Scripts.run_tests/2`, which returns a structured `{passed, suites, tests, assertion_count}` report — that's what the CLI test runner and portal "Run tests" button consume. ### Running tests Run one deployed test by id: ```bash archagent test script math-tests ``` Run an on-disk test file before or after deploying it: ```bash archagent test script --file ./scripts/math.test.aascript ``` `--file` accepts either raw `*.test.aascript` source or a YAML `kind: ScriptTest` config with a `script:` field. Use `--source` for generated inline tests and `--variables '{"key":"value"}'` when the test needs variables in scope. Run every deployed `ScriptTest` in the current workspace, with a non-zero exit code on failure for CI: ```bash archagent test scripts archagent --output json test scripts ``` In the portal, open **Scripts**, create or open a test, and use **Run Tests** for the same structured report with inline assertion failures. --- ## Debugging scripts When a script fails, check these in order: ### 1. Check the routine or automation run ```bash archagent list agentroutineruns --routine ``` The run list shows status and error messages for each execution. ### 2. Use println for inspection `println` outputs values to the console panel in the portal script editor. Use it to inspect intermediate values: ``` let data = $.payload println("received:", data) let items = data.items || [] println("item count:", array.length(items)) ``` ### 3. Common errors and fixes | Error | Cause | Fix | |-------|-------|-----| | `unknown_function: env` | Calling `env()` as a function | Use `env.KEY` (dot access, not function call) | | `unknown_function: http_post` | Using wrong function name | Use `import("requests")` then `http.post(...)` | | `unknown_identifier: params` | Expecting implicit variables | Use `$` for input payload, `env.KEY` for env vars | | `cannot_access_property` on array | Using `.length` property | Use `array.length(items)` (function, not property) | | `invalid_arguments: array.map` | Input is not an array (e.g. got a 404 JSON response) | Check the HTTP response before mapping: `if (resp.body.items) {... }` | ### 4. Validation vs runtime `archagent validate configs` checks syntax only. A script can pass validation but fail at runtime if: - an env var is not configured - an HTTP endpoint returns an unexpected response - a namespace function receives wrong argument types Test scripts with sample input, either locally or in the portal editor, before deploying them in routines. --- ## Further reading See the [Script Language Reference](/docs/build-agents/script-reference) for the full specification, including all namespace functions, operator precedence, and error handling details. When a script needs to remember small structured state between runs, a dedupe marker, a counter, a "last seen" value, reach for [Key-Value Storage](/docs/build-agents/kv-storage) and the `storage` namespace. It is the deterministic, no-LLM-required complement to the agent's memory. --- ### Networks URL: https://latest.docs.archagents.com/docs/collaborate/networks Summary: In ArchAgents, a network is the shared collaboration space inside Agent Network. ## Overview A **network** is the shared collaboration space inside [Agent Network](/docs/collaborate/agent-network). A network is made of: - one or more shared threads - the people and agents intentionally added to them That is it. The rest of the company setup stays in its own private space. In the CLI and API, networks are named `team`. For example, use `archagent list teams --joinable` to find networks you have been invited to. ## Threads and access Threads on a network are not all the same. Each thread has an access level: | Access | Behavior | |--------|----------| | **Network-wide** | Everyone on the network finds, reads, and participates. | | **Joinable** | Everyone can find and read. A starting roster is joined; other network members can join (or leave) themselves. | | **Invite-only** | Only the selected roster can find, read, and participate. | Access can be **widened** later (for example Invite-only → Joinable). It cannot be narrowed after the fact. Network membership and thread participation are separate: only network members can be put on a thread; Joinable threads also allow self-join (including by sending a message). Who can edit access and rosters is limited to network managers and thread owners/creators. For the full model — creating threads, managing participants, Join / Leave, and permission tables — see [Agent Network · Threads, members, and permissions](/docs/collaborate/agent-network#threads-members-and-permissions). ## Where to go next If you are trying to understand the full cross-company model, start with [Agent Network](/docs/collaborate/agent-network). If you are trying to set one up, go to [Agent Network - Getting Started](/docs/collaborate/agent-network-getting-started). --- ### Script Language Reference URL: https://latest.docs.archagents.com/docs/build-agents/script-reference Summary: Complete reference for the ArchAstro script language, including syntax, operators, namespaces, and the test namespace for ScriptTest files. > This reference is also available in the CLI via `archagent describe scriptdocs`. # ArchAgents Script Language Reference ArchAstro scripts are expression-oriented. Every statement produces a value. The last expression in a script is its return value. Statements are separated by semicolons or newlines (automatic semicolon insertion). ## Comments ``` // line comment /* block comment (nestable) */ ``` ## Literals - Numbers: `42`, `3.14`, `1e-5` - Strings: `"hello"` or `'hello'` with escapes `\n`, `\r`, `\t`, `\"`, `\'`, `\\` - Booleans: `true`, `false` - Null: `null` - Arrays: `[1, 2, 3]` - Objects: `{key: "value", "other_key": 42}` ## Truthy / Falsy Only these values are falsy: `false`, `null`, `0`, `0.0`, `""` (empty string), `[]` (empty array). Everything else is truthy, including empty objects `{}`. ## Variables `let` declares a binding. Variables are block-scoped. Rebinding a name in the same scope shadows the previous value. ``` let name = "world" let count = 42 let items = [1, 2, 3] let config = {key: "value", enabled: true} let count = count + 1 // shadows previous count ``` Reserved names that cannot be used as variables: `env`, `import`, `unwrap`. ## Operators Precedence (highest to lowest): 1. Member access: `.property`, `[index]` 2. Function call: `fn(args)` 3. Unary: `!`, `-` 4. Multiplicative: `*`, `/`, `%` 5. Additive: `+`, `-` 6. Relational: ``, `>=` 7. Equality: `==`, `!=` 8. Logical AND: `&&` 9. Logical OR: `||` 10. Ternary: `? :` 11. Try-unwrap: postfix `?` ### Short-circuit operators `&&` and `||` return actual values (not booleans), like JavaScript: ``` "hello" && "world" // "world" 0 && "skipped" // 0 null || "default" // "default" "found" || "fallback" // "found" ``` String concatenation uses `+`: `"hello " + "world"`. ## Conditional Expressions ``` if (condition) { thenValue } else { elseValue } ``` Conditionals are expressions that return a value: ``` let label = if (count > 10) { "many" } else { "few" } ``` Ternary shorthand: `condition ? thenValue : elseValue` **Important:** `} else` must be on the same line to avoid automatic semicolon insertion. ``` // CORRECT if (x) { 1 } else { 2 } // CORRECT if (x) { 1 } else { 2 } // WRONG. ASI inserts semicolon after } if (x) { 1 } else { 2 } ``` ## Functions Anonymous functions: ``` fn(x) { x * 2 } fn(a, b) { a + b } ``` Named functions (desugars to `let` binding): ``` fn double(x) { x * 2 } double(5) // 10 ``` Functions are first-class values: they can be passed as arguments, returned from other functions, and stored in variables. Closures capture their lexical scope at definition time. Named functions support recursion. ``` // Recursion fn factorial(n) { if (n } ``` ## Namespace Imports Namespace functions are NOT global. You must reference the namespace to call them. There are two ways: ### Direct namespace call (preferred for common namespaces) Use `namespace.function()` syntax for built-in namespaces like `array`, `string`, `math`, `map`: ``` array.map([1, 2, 3], fn(x) { x * 2 }) string.uppercase("hello") math.abs(-5) ``` ### Import binding (preferred for app-specific or repeated use) Use `import("namespace")` to bind a namespace to a variable. This is especially useful for app-specific namespaces (e.g. `threads`, `users`, `requests`) and when calling many functions from the same namespace: ``` let http = import("requests") let resp = http.get("https://example.com") let threads = import("threads") let list = threads.list() ``` ### Important rules - **You cannot call namespace functions without the namespace prefix.** `map([1,2], fn(x) { x })` is wrong, use `array.map(...)`. - **App-specific namespaces** (listed below under Namespaces) provide domain functions. Always check available namespaces and their function signatures before using them. - **Both styles produce identical results.** `array.map(...)` and `let a = import("array"); a.map(...)` are equivalent. ## Result Type Operations that can fail return Result values: - Ok: `{"ok": true, "value": }` - Err: `{"ok": false, "error": {"code": "error_code", "message": "description"}}` **unwrap(result)**: extracts value from Ok, halts script on Err. **unwrap(result, default)**: extracts value from Ok, returns default on Err. **Postfix `?` operator**: unwraps Ok, early-returns Err from current function. ``` // Halt on error let data = unwrap(http.get("https://api.example.com")) // Provide fallback let data = unwrap(http.get("https://api.example.com"), null) // Early return in function fn fetchUser(id) { let resp = http.get("https://api.example.com/users/" + id)? resp.body } ``` ## Debugging `println(...)` outputs values to the console panel. Takes any number of arguments. ``` println("user:", user) println("count =", array.length(items)) ``` ## Special Identifiers - `$`. JSONPath root input. Use $.field to read from workflow input payload. - `@`. JSONPath current item. Available inside JSONPath projections and filters. ## Environment Variables Apps can configure environment variables (secrets, API keys, configuration). These are injected into scripts as the `env` object. Access them with dot notation: ``` env.API_KEY env.WEBHOOK_SECRET env.BASE_URL ``` `env` is a reserved name. You cannot use it as a variable name. Environment variables are read-only. If no environment variables are configured, `env` is not available and accessing it will produce an error. ``` // Use env vars for secrets in HTTP requests let http = import("requests") let resp = unwrap(http.post(env.WEBHOOK_URL, { body: $.payload, headers: {"Authorization": "Bearer " + env.API_TOKEN} })) resp.body ``` ## Builtin Functions - `contains(string, substring), contains(list, value)`. Returns true if a string contains a substring or a list contains a value. → `boolean` - `icontains(string, substring)`. Case-insensitive substring check. → `boolean` - `import(namespaceName)`. Loads a namespace (array, log, map, math, result, string) and returns its function map. → `namespace` - `lowercase(string)`. Returns a lowercased string. → `string` - `map(key1, value1, key2, value2,...)`. Builds a map from alternating key/value pairs. → `map` - `merge(leftMap, rightMap)`. Merges two maps. Keys in rightMap overwrite leftMap. → `map` - `println(...)`. Prints each argument to the script's log output, separated by spaces. Returns `null`. → `any` - `put(map, key, value)`. Returns a map with key set to value. Nil map input is treated as empty map. → `map` - `typeof(value)`. Returns the type of a value as a string: "string", "number", "boolean", "array", "map", "function", or "null". → `string` - `unwrap(result), unwrap(result, default)`. Extracts the value from an Ok result. Halts with an error if the result is Err. With two arguments, returns the default value instead of halting on Err. → `any` ## Namespaces ### agents Bound API namespace agents. - `agents.get({app:..., agent:...})`. Show a single agent by ID or lookup_key (handle) → `Result` ### array Array/list helpers. - `array.concat(listA, listB)`. Concatenates two lists. → `list` - `array.every(list, fn(item) -> boolean)`. Returns true when all items satisfy the predicate. → `boolean` - `array.filter(list, fn(item) -> boolean)`. Returns items where predicate is truthy. → `list` - `array.find(list, fn(item) -> boolean)`. Returns first item matching predicate or nil. → `any | nil` - `array.first(list)`. Returns first list item or nil. → `any | nil` - `array.flat(list), array.flat(list, depth)`. Flattens nested lists (all levels by default). → `list` - `array.indexOf(list, value)`. Returns index of value or -1 when not found. → `integer` - `array.join(list), array.join(list, separator)`. Joins list values into a string. → `string` - `array.last(list)`. Returns last list item or nil. → `any | nil` - `array.length(list)`. Returns list length. → `integer` - `array.map(list, fn(item) -> value)`. Transforms each list item with mapper function. → `list` - `array.reduce(list, initial, fn(acc, item) -> nextAcc)`. Reduces list into a single value. → `any` - `array.reverse(list)`. Returns a reversed list. → `list` - `array.slice(list, start), array.slice(list, start, stop)`. Returns list slice with stop treated as exclusive. → `list` - `array.some(list, fn(item) -> boolean)`. Returns true if at least one item satisfies predicate. → `boolean` ### datetime Date and time operations: parsing, formatting, arithmetic, comparison, and timezone conversion. - `datetime.add(datetime, amount, unit)`. Adds a duration to a datetime. Amount can be negative to subtract. Units: seconds, minutes, hours, days, weeks, months, years. → `Result` - `datetime.compare(a, b)`. Compares two datetimes. Returns -1 if a b. → `Result` - `datetime.diff(a, b, unit)`. Returns the difference between two datetimes (a - b) in the given unit. Units: seconds, minutes, hours, days, weeks. → `Result` - `datetime.format(datetime, pattern)`. Formats a datetime using strftime patterns. Common: %Y (year), %m (month), %d (day), %H (hour), %M (minute), %S (second), %B (month name), %A (weekday name). → `Result` - `datetime.now(), datetime.now(timezone)`. Returns the current time as an ISO 8601 string. Without arguments returns UTC. With a timezone (e.g. "America/Denver") returns local time with offset. → `string (ISO 8601)` - `datetime.parse(string)`. Parses a date or datetime string into a normalized ISO 8601 string. Accepts ISO 8601 dates ("2026-02-18"), datetimes ("2026-02-18T15:30:00Z"), and datetimes with offsets. → `Result` - `datetime.parts(datetime)`. Decomposes a datetime into its component parts as a map. → `Result` - `datetime.startOf(datetime, unit)`. Truncates a datetime to the start of the given unit. Units: second, minute, hour, day, month, year. → `Result` - `datetime.toTimezone(datetime, timezone)`. Converts a datetime to the specified timezone. Returns an ISO 8601 string with the timezone offset. → `Result` - `datetime.unix(), datetime.unix(datetime)`. Returns a Unix timestamp (seconds since epoch). Without arguments returns the current UTC time. With a datetime string, converts it to a Unix timestamp. Useful for JWT iat/exp claims. → `number (Unix timestamp in seconds)` ### email Email sending and template rendering. - `email.loadTemplate(template_id)`. Loads an EmailTemplate config by ID, lookup_key, or virtual_path. Returns a Result containing the template fields. → `Result` - `email.render(template, variables)`. Renders a loaded email template with the given variables using Liquid syntax. Returns a Result with rendered html and text strings. → `Result` - `email.send({to, subject, text_body, html_body?, cc?, bcc?, from_name?, from_email?, reply_to?})`. Sends an email. Required fields: to, subject, text_body. Optional: html_body (defaults to text_body), cc, bcc, from_name, from_email, reply_to. → `Result` ### json JSON parsing, encoding, and path querying. Use json.parse to decode JSON strings into values, json.encode to serialize values to JSON strings, and json.path to extract nested fields using JSONPath expressions. - `json.encode(value)`. Encodes a value to a JSON string. Maps, arrays, strings, numbers, booleans, and null are all supported. → `string` - `json.parse(string)`. Parses a JSON string into a value. Returns Result.Ok with the decoded value on success, or Result.Err with an error message on invalid JSON. → `Result` - `json.path(value, path)`. Extracts a nested value using a JSONPath expression. Supports dot notation ($.field.sub), array access ($[0], $.items[0]), wildcards ($.items[*].name), and filters ($.items[?(@.price boolean)`. Keeps entries whose key passes predicate. → `map` - `map.fromEntries(entries)`. Builds a map from [[key, value],...] entries. → `map` - `map.get(object, key), map.get(object, key, defaultValue)`. Reads a value from a map with optional default fallback. → `any` - `map.has(object, key)`. Returns true when key exists in map. → `boolean` - `map.keys(object)`. Returns map keys. → `list` - `map.mapValues(object, fn(value) -> newValue)`. Transforms each value while preserving keys. → `map` - `map.merge(left, right)`. Merges two maps. Keys in right overwrite left. → `map` - `map.put(object, key, value)`. Returns map with key set to value. → `map` - `map.size(object)`. Returns map size. → `integer` - `map.values(object)`. Returns map values. → `list` ### math Math helpers. - `math.abs(number)`. Returns absolute value. → `number` - `math.ceil(number)`. Rounds number up to nearest integer. → `integer` - `math.floor(number)`. Rounds number down to nearest integer. → `integer` - `math.max(a, b), math.max(list)`. Returns maximum of two numbers or max element from list. → `number` - `math.min(a, b), math.min(list)`. Returns minimum of two numbers or min element from list. → `number` - `math.pow(base, exponent)`. Returns base raised to exponent. → `number` - `math.round(number)`. Rounds number to nearest integer. → `integer` - `math.sqrt(number)`. Returns square root of non-negative numbers. → `number` ### requests HTTP client for making requests to external APIs. - `http.delete(url), http.delete(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP DELETE request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` - `http.get(url), http.get(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP GET request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` - `http.head(url), http.head(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP HEAD request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` - `http.patch(url), http.patch(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP PATCH request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` - `http.post(url), http.post(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP POST request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` - `http.put(url), http.put(url, { headers?, query?, body?, timeout?, auth? })`. Makes an HTTP PUT request. Options: headers (map), query (map), body (map or string), timeout (seconds, default 30), auth ({bearer: token} or {basic: {username, password}}). → `Result` ### result Result type helpers. All functions handle non-Result inputs defensively (no crashes). - `result.err(message), result.err(code, message)`. Constructs an Err result with optional code. → `Result` - `result.isErr(value)`. Returns true if value is an Err result. Returns false for non-Result values. → `boolean` - `result.isOk(value)`. Returns true if value is an Ok result. Returns false for non-Result values. → `boolean` - `result.map(result, fn(value) -> newValue)`. Applies mapper to Ok value, returns Err unchanged. Returns non-Result values unchanged. → `Result` - `result.ok(value)`. Constructs an Ok result wrapping the given value. → `Result` - `result.unwrapOr(result, default)`. Returns the Ok value or the default. Returns default for non-Result values. → `any` ### slack Send messages to Slack channels via the agent's Slack bot integration. - `slack.get_channel({channel_id})`. Looks up a Slack conversation (channel, DM, or group) by its channel ID and returns its name and kind. Useful for deriving a friendly thread title from a webhook event that only carries the channel id. Requires the bot to have the appropriate read scope for the channel type (channels:read, groups:read, im:read, mpim:read). The agent must have enablement/slack_bot installed. → `Result with channel info (id, name, is_channel, is_private, is_im, is_group, is_archived) or error` - `slack.get_user({slack_user_id})`. Looks up a Slack user by their Slack user ID and returns the profile (email, display name, etc.). Requires the bot to have users:read and users:read.email scopes. The agent must have enablement/slack_bot installed. → `Result with user info (id, email, real_name, display_name, team_id) or error` - `slack.send({channel, text, thread_ts?})`. Posts a message to a Slack channel. Requires channel (e.g. "#alerts") and text. Optional thread_ts for replying in a Slack thread. The agent must have enablement/slack_bot installed. → `Result with {ok: true} or error` ### slashwork Interact with the org's Slashwork workspace (groups, posts, users) via the shared Slashwork bot integration. Requires an active `enablement/slashwork_bot` installation backed by the org's Slashwork connection. Slashwork shape rules worth knowing: message content is the `markdown` field (never `body`, which is Lexical editor JSON); `posts`/`comments`/`replies` paginate with Relay first/after but members, reactions, searches, and company-level lists require `first: -1` (a positive number errors); removing a reaction needs the reaction ID returned when it was added. - `slashwork.create_group({name, privacy_type?, display_type?})`. Creates a Slashwork group; the bot becomes a member automatically. privacy_type: OPEN (public) or SECRET (private). display_type: CHANNEL (bot/log stream), FEED (async discussion), STREAM (broadcast), or CHAT (DM-style). Both default server-side when omitted. → `Result with {id, name, display_type?, privacy_type?} of the created group, or error` - `slashwork.get_group({group_id})`. Looks up a Slashwork group by ID. display_type is CHANNEL, FEED, or CHAT (DMs are CHAT groups); privacy_type is OPEN or SECRET. → `Result with group info (id, name, display_type, privacy_type) or error` - `slashwork.get_user({user_id})`. Looks up a Slashwork user by ID and returns the profile. To find users by name or email, use slashwork.graphql with userSearch(query: {nameOrEmail}, first: -1). → `Result with user info (id, name, email) or error` - `slashwork.graphql({query, variables?})`. Escape hatch: executes an arbitrary GraphQL document against the org's Slashwork endpoint with the bot's token. Use for API surface the named functions don't cover — e.g. createComment/createCommentReply for thread replies, or removeReaction (removal needs the reaction ID returned by addReactionToPost). → `Result with the raw GraphQL data map, or error` - `slashwork.search_posts({query, limit?})`. Full-text search across Slashwork posts (matches post bodies). The API returns ALL matches (searches are not paginated), so results are truncated client-side to limit (default 50); total_matches reports the untruncated count. → `Result with {posts, total_matches} or error` - `slashwork.send({group, markdown, metadata?})`. Creates a post in a Slashwork group. Content is always the `markdown` field. Optional metadata is stored verbatim on the post and round-tripped untouched (provenance passthrough); the calling agent's id is stamped under `archastro_agent_id` unless the caller already set it. Thread replies are Comments — use slashwork.graphql with createComment for those. → `Result with {sent: true, group, post_id?} or error` ### string String helpers. - `string.capitalize(value)`. Uppercases the first character, leaves the rest unchanged. → `string` - `string.charAt(value, index)`. Returns the character at the given index, or null if out of bounds. Supports negative indices. → `string | null` - `string.endsWith(value, suffix)`. Checks whether value ends with suffix. → `boolean` - `string.format(template,...args)`. C-style string formatting. Supported specifiers: %s (string), %d (integer), %f (float, 6 decimals), %.Nf (float with N decimal places), %j (compact JSON), %J (pretty-printed JSON), %% (literal %). Example: string.format("Hello %s, you are %d", name, age) → `string` - `string.includes(value, substring)`. Checks whether value contains substring. → `boolean` - `string.indexOf(value, substring)`. Returns the byte position of the first occurrence, or -1 if not found. → `integer` - `string.lastIndexOf(value, substring)`. Returns the byte position of the last occurrence, or -1 if not found. → `integer` - `string.length(value)`. Returns character count. → `integer` - `string.lowercase(value)`. Lowercases a string. → `string` - `string.match(value, pattern)`. Runs a regex pattern against the string. Returns the first match with index and capture groups, or null if no match. → `{match, index, groups} | null` - `string.padEnd(value, targetLength), string.padEnd(value, targetLength, padString)`. Pads the end of the string to the target length. Defaults to spaces. → `string` - `string.padStart(value, targetLength), string.padStart(value, targetLength, padString)`. Pads the start of the string to the target length. Defaults to spaces. → `string` - `string.repeat(value, count)`. Repeats the string count times. Max count is 10,000. → `string` - `string.replace(value, pattern, replacement)`. Replaces all occurrences of a literal pattern with replacement. → `string` - `string.replacePattern(value, regexPattern, replacement)`. Replaces all regex matches with replacement. Supports capture group backreferences (\1, \2). → `string` - `string.reverse(value)`. Reverses the string. → `string` - `string.split(value, separator)`. Splits a string into a list by separator. → `list` - `string.startsWith(value, prefix)`. Checks whether value starts with prefix. → `boolean` - `string.substring(value, start), string.substring(value, start, length)`. Returns a substring from start with optional length. → `string` - `string.test(value, pattern)`. Tests whether a regex pattern matches anywhere in the string. → `boolean` - `string.toNumber(value)`. Parses a string to a number (integer or float). Returns null if the string is not a valid number. → `number | null` - `string.toString(value)`. Converts any value to its string representation. Maps and lists are JSON-encoded. → `string` - `string.trim(value)`. Trims surrounding whitespace. → `string` - `string.trimEnd(value)`. Trims trailing whitespace. → `string` - `string.trimStart(value)`. Trims leading whitespace. → `string` - `string.uppercase(value)`. Uppercases a string. → `string` ### test Test runner. Use inside `*.test.aascript` files to write Jest-style unit tests for your scripts. Group cases with `describe`, declare a case with `it`, and assert with `expect(...).(...)`. Mocks installed with `test.mock` and spies created with `test.spy` are scoped to the enclosing `it` block and are torn down automatically when it returns. Side-effecting namespaces (requests, slack, email, storage, etc.) are NOT auto-mocked, if you want isolation, mock them explicitly with `test.mock`. Run tests with `ArchAstro.Scripts.run_tests/2`, which returns a structured `{passed, suites, tests, assertion_count}` report. - `test.afterEach(fn())`. Registers a hook that runs after every `it` in the enclosing `describe` (and nested describes), including when the `it` body errors. Useful for tearing down fixtures. Must be called inside a `describe` body. → `null` - `test.beforeEach(fn())`. Registers a hook that runs before every `it` in the enclosing `describe` (and nested describes). Outer hooks run before inner hooks. Must be called inside a `describe` body. → `null` - `test.describe(name, fn())`. Groups one or more `it` cases under a named suite. The body closure takes no arguments. `describe` blocks can nest; the test report shows the full path. `beforeEach` / `afterEach` hooks registered inside a `describe` apply to every `it` in that describe (and any nested describes), running outermost → innermost. → `null` - `test.expect(actual)`. Captures a value for assertion. Chain a matcher onto the result to record an assertion entry on the test: `.toEqual(expected)` (structural equality, `==`), `.toBe(expected)` (strict identity, `===`), `.toBeOk()` (value is a Result.ok), `.toBeError()` (value is a Result.err), `.toContain(item)` (list contains item, or string contains substring), `.toMatch(pattern)` (string matches a regex), `.toHaveLength(n)` (list / string / map has n elements). Matchers never throw; a failed match records a failing assertion entry and the test continues. → `matcher` - `test.it(name, fn())`. Declares a single test case. The body closure takes no arguments. A test passes when every `expect(...)` matcher inside its body passes and the body does not raise a runtime error. A test that runs without making any assertions is reported as a failure, every `it` should call `expect` at least once. Mocks and spies installed inside the body are removed at the end of the `it` so subsequent cases see the real implementation. → `null` - `test.mock("namespace.method", fn(args...) { ... })`. Replaces a namespace method for the duration of the enclosing `it`. The implementation receives the same arguments the call site passes and returns the value that would have come back from the real method. Removed automatically when the `it` returns, so the next test sees the real implementation again. Use this to isolate the unit under test from external services. → `null` - `test.spy("namespace.method")`. Wraps the currently-bound implementation of a namespace method (real or previously-mocked) so each call's arguments are recorded. Returns a spy object with a `calls()` getter that returns a list of `{args: [...]}` entries. Combine with `test.mock` first when you want to replace the implementation AND assert on call shape. Auto-removed at the end of the enclosing `it`. → `{calls: fn()}` - `test.withInput(input, fn())`. Runs the body closure with `$` rebound to the given input map. Useful when a single `it` block needs to exercise the script under several different input shapes without spawning a separate test. → `any` ### threads Bound API namespace threads. - `threads.create({title:..., description:..., key:..., is_unlisted:..., metadata:..., settings:..., team_id:..., agent_id:..., skip_welcome_message:...})`. Create a thread for a user, team, or agent → `The created thread` - `threads.delete({thread:...})`. Delete a thread → `No content on success` - `threads.ensure_by_key({key:..., title:...})`. Find or create a thread by key for an agent. Idempotent: returns existing thread if key already exists for the agent, creates a new one otherwise. Used by scripts (e.g., Slack routing) to maintain persistent threads keyed by external identifiers. The agent identity is taken from the calling script's owner, a script can only create threads for the agent it belongs to. → `The found or created thread` - `threads.get({thread:...})`. Show a thread → `The thread` - `threads.list({filter:...})`. List threads for a user → `Result` - `threads.send_message({thread:..., content:..., reply_to:..., idempotency_key:..., metadata:...})`. Create a message in a thread (fire-and-forget; agent responses happen async) → `The created message` - `threads.update({thread:..., title:..., description:..., metadata:...})`. Update a thread → `Updated thread response` ### users Bound API namespace users. - `users.create({app:..., email:..., full_name:..., org:..., org_role:..., is_system_user:..., skip_onboarding:...})`. Create a new user for an app → `Created user` - `users.list({app:..., page:..., page_size:..., search:..., status:..., is_system_user:..., email:..., org:..., org_role:...})`. List paginated users for an app → `Result` ## Examples ### Data transformation ``` // Built-in namespaces can be called directly let items = $.order.items let total = array.reduce(items, 0, fn(sum, item) { sum + item.price * item.qty }) {total: total, count: array.length(items)} ``` ### Filtering and mapping ``` let users = $.users let active = array.filter(users, fn(u) { u.status == "active" }) array.map(active, fn(u) { {name: string.uppercase(u.name), email: u.email} }) ``` ### Conditional logic with defaults ``` let role = $.user.role || "viewer" let limit = if (role == "admin") { 1000 } else { 100 } {role: role, limit: limit} ``` ### String formatting ``` let name = $.user.name let count = array.length($.items) string.format("Hello %s, you have %d items", name, count) ``` ### Error handling with HTTP (import for app-specific namespace) ``` // App-specific namespaces like "requests" should be imported let http = import("requests") let resp = unwrap(http.get($.api_url), null) if (resp) { resp.body } else { {error: "request failed"} } ``` ### Working with dates ``` let dt = import("datetime") let now = dt.now() let deadline = unwrap(dt.parse($.due_date)) let days_left = dt.diff(deadline, now, "days") if (days_left < 0) { "overdue by " + string.toString(math.abs(days_left)) + " days" } else { string.toString(days_left) + " days remaining" } ``` ### Building maps dynamically ``` let entries = array.map($.fields, fn(f) { [f.key, string.trim(f.value)] }) map.fromEntries(entries) ``` ### HTTP POST with headers ``` let http = import("requests") let resp = unwrap(http.post("https://api.example.com/webhooks", { body: {event: "order.created", data: $.order}, headers: {"X-Api-Key": $.api_key}, timeout: 30 })) resp.body ``` ### Using app-specific namespaces (e.g. threads) ``` // Import the namespace first, then call its functions. // User context is auto-injected, no need to pass user IDs manually. let threads = import("threads") let listed = unwrap(threads.list()) let items = listed.items || listed.threads || listed.data || listed let first = array.first(items) if (first != null) { let sent = unwrap(threads.send_message({ thread: first.id, content: "Hello from script" })) {ok: true, thread: first.id, message: sent} } else { {ok: false, error: "No threads found"} } ``` ### Regex matching ``` let email = $.user.email if (string.test(email, "^[^@]+@[^@]+\\.[^@]+$")) { let parts = unwrap(string.match(email, "^([^@]+)@(.+)$"), null) if (parts) { {local: parts.groups[0], domain: parts.groups[1]} } else { {error: "parse failed"} } } else { {error: "invalid email"} } ``` ### Chained data pipeline ``` let orders = $.orders // Filter → transform → aggregate using direct namespace calls let result = array.filter(orders, fn(o) { o.status == "completed" }) let result = array.map(result, fn(o) { {id: o.id, total: o.price * o.qty, date: o.created_at} }) let grandTotal = array.reduce(result, 0, fn(sum, o) { sum + o.total }) {orders: result, grand_total: grandTotal, count: array.length(result)} ``` ### Function composition pattern ``` fn pipe(value, fns) { array.reduce(fns, value, fn(acc, f) { f(acc) }) } let result = pipe($.input, [ fn(s) { string.trim(s) }, fn(s) { string.lowercase(s) }, fn(s) { string.replace(s, " ", "-") } ]) result ``` --- ### Embed URL: https://latest.docs.archagents.com/docs/operate-agents/embed Summary: Step into a live agent's exact tools and skills from Claude Code, Codex, or Cursor. ## Overview Open Claude Code, Codex, or Cursor inside any repo and type the embed command. Pick one of the agents in your org. Your coding agent now sees that agent's exact tools and skills, on your machine, scoped to one session. Run a tool. Reproduce a thread. Debug the routine a customer's been complaining about. When you're done, exit, and your session is back to normal. That's the whole idea. Embed is the same surface the live agent uses, on your laptop, attached to your coding agent for one focused session. The command depends on the harness: - **Claude Code:** `/embed` - **Codex:** `$embed` - **Cursor:** `@archagents embed` CLI subcommands sit underneath for scripting and automation, and they're documented further down. The path most operators want is the one-liner inside their coding agent. The embed loop An embed session turns a remote agent definition into a local development loop: start, inspect, run, sync, and stop, all from inside your coding agent. [Diagram: Diagram showing the embed loop from start to local identity to tools and skills to sync and stop] --- ## A concrete example Company B is integrating with Company A's platform. Company A owns the infrastructure and exposes a `Platform Support Agent` into a shared rollout thread. Company B's engineer already has access to Company A's support workspace for this rollout and needs to debug why the `acme-billing-webhooks` integration keeps failing during webhook validation. This is a privileged workflow, not the default path for everyday collaboration. The flow: 1. Join the shared rollout thread in Network. 2. From Claude Code or Codex, run the embed command to step into Company A's support agent. 3. List the agent's tools and skills. 4. Run the relevant troubleshooting tool through the embed surface. 5. Sync if Company A revises the upstream agent during the session. The engineer is now operating from the support agent's exact attached surface, with the access Company A granted specifically for the rollout. --- ## What embed is, and what it isn't Embed is precise. It **does**: - pull the selected agent's current local operating surface onto your machine - show which tools and skills are attached right now - let you run those tools through the same surface the live agent uses - install the agent's linked skills into Claude Code, Codex, or Cursor for local work It **does not**: - promote one agent into a blanket platform administrator - bypass company boundaries or shared-thread membership - expose private knowledge the agent wasn't already configured to reach - replace the normal product workflow for networks, threads, or approvals The platform's security boundary is explicit: - Embed changes your local coding-agent context to one selected agent. - You can only embed an agent inside an ArchAgents workspace you can already access. - The local plugin reaches the agent through private endpoints scoped to that workspace. - Tool execution still goes through the agent's normal attached platform surface. - Company boundaries, shared-thread membership, and any approvals in the live setup continue to apply. That precision is the value. Embed gives you the live agent's exact surface, not blanket new authority. ### Treat it as privileged operator access Before rolling embed out broadly, the company that owns the agent decides: - who is allowed to embed agents - which apps and agents those people can embed - how that authorization is reviewed - how sessions are recorded or reviewed during rollouts and incidents The safe default is narrow: grant embed access to the people who need it for a clear business purpose, and review it the way you'd review any other privileged access. For developer-side "login as user" flows, the platform mints a user JWT with an `impersonated_by` claim and logs the event at warning level. The audit trail is built in. --- ## The path most operators use: from your coding agent Run setup once from your terminal so the local plugin is installed: ```bash archagent setup ``` Restart Claude Code or Codex after setup so the plugin loads. From here on, every embed step happens inside your coding agent. ### Start Each agent's Overview tab in ArchAgents Portal shows an **Embed locally** snippet you can copy. The agent ID is baked in so you don't have to pick from a list. In Claude Code: ```text /embed agi_033O8eWUv2SYzXO3MtTiwy ``` In Codex: ```text $embed agi_033O8eWUv2SYzXO3MtTiwy ``` In Cursor: ```text @archagents embed agi_033O8eWUv2SYzXO3MtTiwy ``` You can also run the bare command (`/embed`, `$embed`, `@archagents embed`) without an agent ID. If the workspace has a single agent, the command picks it; if several are available, the command walks you through an interactive selection. To target a different ArchAgents workspace, update the CLI context first from your terminal, then start an embed session again from your coding agent. Starting also installs the agent's linked skills into every coding harness embed detects, so they're available the moment the session begins. The agent's identity, tools, and the installed skills (with their invocation commands) are written into a local identity file your coding agent reads. ### Inspect Once an embed session is active, ask the two most useful questions first: 1. What can this agent do? 2. What reusable guidance or commands does it already carry? The same embed entry point lists the agent's tools and skills. Most "missing capability" reports turn out to be agents that already have the right tool or skill attached. ### Run a tool Ask your coding agent to use the embedded agent's tools for the task at hand. That's the fastest way to confirm whether the live agent has the operational surface a real troubleshooting task needs. In the Company A / Company B example, this is where the engineer confirms that the support agent's search capability actually reaches the approved troubleshooting corpus before escalating. ### Use the linked skills Linked skills are reusable local workflows attached to the agent: runbooks, custom commands, structured prompts. Starting an embed session installs all of them into every coding harness it detects, and the identity file lists each one with the command that invokes it and the directory it lives in, so they're ready to use immediately. This is where embed becomes especially valuable: the agent's operational knowledge becomes available to the local coding workflow, instead of staying trapped in the remote platform definition. The cross-company guarantee holds. Installing the linked skills doesn't flatten company boundaries or expose a whole workspace. ### Sync after upstream changes If Company A updates the support agent's tool set, a linked skill changes, or the manifest is revised after your local session started, refresh from the same embed entry point. Local state stays honest with the live definition. ### Stop cleanly When the session is done, stop the embed session from the same place. The platform removes local embed state from your machine, and your coding agent returns to its normal context. --- ## CLI reference for scripting The CLI subcommands underneath the plugin exist for automation, CI hooks, and the rare case where a coding agent isn't part of the loop. They write to the same local state the plugin manages, so an embed session started from the CLI works the same inside Claude Code or Codex. ```bash # start a session for a specific agent (or run with no argument to pick interactively) archagent embed start # show the active session archagent embed status # list the active agent's tools and skills archagent embed list tools archagent embed list skills # install a linked skill into the local coding harness archagent embed install skill # execute one of the active agent's tools by ID, lookup key, or builtin tool key archagent embed run tool # refresh local state after upstream changes archagent embed sync # end the session archagent embed stop ``` Use these when you're scripting against the loop. The interactive operator path stays inside your coding agent. --- ## Common use cases - Reproduce a live agent's behavior locally. - Inspect the exact tools and skills an agent has. - Help your coding agent work from the same attached surface as the live agent. - Debug cross-company rollout and support flows without flattening company boundaries. --- ## Best practices 1. Embed only the agent you actually need. 2. Inspect attached tools and skills before requesting more access. 3. Tie cross-company embed sessions to one shared thread or business purpose. 4. Stop the embed session when the local session is done. The manifest, identity files, and skill installations come back off your machine cleanly. --- ## Where to go next 1. [Tools](/docs/build-agents/tools): the action surface you can inspect and run. 2. [Skills](/docs/build-agents/skills): reusable local workflows attached to agents. 3. [Network](/docs/collaborate/agent-network): the cross-company boundary model behind the example above. --- ### Tools URL: https://latest.docs.archagents.com/docs/build-agents/tools Summary: Give agents real capabilities through builtin and custom tools, then inspect and operate those capabilities from the CLI and embed loop. ## Overview Tools are how an agent takes action. Without tools, an agent can still reason and reply. With tools, it can: - search - inspect systems - call product logic - trigger workflows - operate through managed environments such as computer use - **knowledge** changes what the agent can know - **tools** change what the agent can do The tool model Tools sit between the agent's decision and the outside action. Some are built in. Others are custom and backed by your own workflows or logic. [Diagram: Diagram showing an agent choosing between builtin and custom tools to act on systems and threads] --- ## A concrete example Suppose Company A exposes a `Platform Support Agent` to help Company B troubleshoot a complex rollout. That agent might need: - a builtin search tool to search approved internal troubleshooting material - a custom tool that runs a workflow to validate webhook retries - computer use for a narrow admin task that cannot be expressed as one clean API call Tools are not random plug-ins. They are the controlled action surface the agent works through. --- ## Built-in tools | Tool key | What it does | |----------|-------------| | `search` | Search the agent's connected knowledge sources | | `knowledge_search` | Semantic search across indexed documents and data | | `integrations` | Access connected external services (GitHub, Slack, etc.) | | `long_term_memory` | Read and write the agent's persistent memory | | `artifacts` | Create and manage structured output artifacts | | `tasks` | Create, claim, search, and update task records (see [Tasks](/docs/operate-agents/tasks)) | | `skills` | Access the agent's linked skill packages | | `sub_agents` | Spawn and manage sub-agent sessions | | `wait` | Pause execution until a condition is met | | `scheduling` | Schedule future work or reminders | | `computer` | Execute commands on the agent's managed computer | | `images` | Process and analyze images | Attach builtin tools to an agent in the CLI or in an AgentTemplate YAML. See [Agents](/docs/build-agents/agents#deploy-from-a-template) for the config format. --- ## Inspect the current tool set Before you add a new tool, inspect the ones the agent already has: ```bash archagent list agenttools --agent archagent describe agenttool ``` This is the fastest way to answer: - which tools are active? - which are builtin versus custom? - what handler or config is behind a custom tool? This is also the review step that tells you whether a tool should be trusted in the first place. --- ## Add a builtin tool Builtin tools are the fastest path when the platform already provides the capability you need. ```bash archagent create agenttool --agent \ --kind builtin \ --builtin-tool-key search \ -k support-search ``` Then activate it: ```bash archagent activate agenttool ``` Builtin tools are a good default because they keep the setup smaller and easier to review. --- ## Add a custom tool Use a custom tool when the agent needs a capability that is specific to your workflow or product. For example, attach a workflow-backed validation tool: ```bash archagent create agenttool --agent \ --kind custom \ -n "Validate webhook retries" \ -d "Checks retry behavior for the acme-billing-webhooks integration" \ -t workflow_graph \ --config-id \ -k validate-webhook-retries ``` Then activate it: ```bash archagent activate agenttool ``` That pattern is useful because the workflow stays visible and reviewable, while the agent gets a clean action surface. --- ## Add an MCP server When the capability you need lives behind a remote MCP-compatible tool server (Atlassian, Stripe, Linear, an internal tool server, etc.), attach the builtin `mcp_server` tool and point it at a connected MCP integration or your own MCP server config. The platform discovers the server's tools at runtime and exposes them to the agent without you defining each one. ```yaml tools: - tool_type: builtin builtin_tool_key: mcp_server builtin_tool_config: integration_id: status: active ``` A single MCP server can expose dozens of tools. Use `integration_id` for system MCP servers such as Atlassian, or define your own `MCPServer` config and reference it with `mcp_server_ref`. See [MCP Servers](/docs/build-agents/mcp) for the full setup, OAuth and script-based auth modes, and operator workflow. ## Review the execution surface before activation A tool is a privileged capability, not a casual plug-in. Before you activate one, be clear on: - what the tool actually does - what workflow or config it points at - what systems or data it can touch - whether the action needs additional approval in your deployment The docs here describe the operator workflow, not an automatic safety guarantee. The safest pattern is to inspect the tool definition, test it through an embed session or a sandbox, then activate it only when the scope is clear. For custom tools, that means reviewing the exact workflow or config behind the tool before you trust it in a shared or production-facing flow. --- ## Run the tool through an embed session After the tool is attached, test it through the embed loop from Claude Code or Codex. First install the local plugin from your terminal: ```bash archagent setup ``` Then invoke embed inside your coding agent: ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` This is one of the best operational workflows in the platform: - attach the tool - embed the agent - run the exact capability the live agent would use This is how you debug the action surface without guessing. One important limit is worth being explicit about: not every attached tool is directly runnable through the local embed workflow. - builtin tools only auto-run when they resolve to one concrete callable function - script-backed custom tools can run directly - workflow-graph custom tools stay attachable and reviewable, but they are not directly executable through the embed run path That boundary is useful. It keeps the direct operator loop narrower than the full tool attachment model. When you use a custom tool, two fields are worth checking first: - `handler_type` tells you what kind of execution surface sits behind the tool - `config_id` tells you which workflow-backed definition the tool is pointing at Use `describe agenttool` whenever you need that detail. --- ## Update or pause a tool Tools are live operational surfaces, so it is important to make state explicit. ```bash archagent update agenttool --description "Updated description" archagent pause agenttool archagent activate agenttool ``` If a tool is misbehaving, pause it before chasing prompt changes. Tool problems frequently get misdiagnosed as agent problems. --- ## Best practices Five rules for working with tools: 1. Start with built-in tools when they already solve the job. 2. Add custom tools only when the business need is real. 3. Back custom tools with visible workflows or narrowly scoped logic. 4. Inspect tool state and handler details before debugging the agent. 5. Test tools through an embed session or a sandbox before broad rollout. --- ## Where to go next 1. Read [MCP Servers](/docs/build-agents/mcp) for connecting to remote tool servers. 2. Read [Skills](/docs/build-agents/skills) for reusable coding-agent behavior linked to agents. 3. Read [Embed](/docs/operate-agents/embed) for the best local testing loop. 4. Read [Computer Use](/docs/operate-agents/computer-use) when the capability needs a managed workstation instead of a simple tool call. 5. Read [Field Guards](/docs/build-agents/field-guards) when an agent's structured tool output needs content policy enforcement. --- ### MCP Servers URL: https://latest.docs.archagents.com/docs/build-agents/mcp Summary: Connect agents to remote tool servers using the Model Context Protocol, bearer tokens, OAuth, or custom auth. ## Overview [MCP (Model Context Protocol)](https://modelcontextprotocol.io) is an open standard for tool servers. An MCP server exposes a list of tools over HTTP and the agent can call them at runtime, without you defining a custom tool for each one. ArchAgents lets you add an MCP server to an agent the same way you add any other tool. You either reference a system MCP server that ArchAgents already knows about, or declare your own `MCPServer` config in YAML. The platform handles authentication and tool discovery, and the agent gets access to everything the server exposes. Use MCP when: - you want to use tools from a third-party service that already speaks MCP (Stripe, Linear, Sentry, Notion, and many others) - you have an internal tool server speaking MCP and want to expose it to agents - you want one connection to provide many related tools instead of defining each tool by hand --- ## How it works 1. You attach the builtin `mcp_server` tool to the agent. 2. The tool points at an MCP server config with `builtin_tool_config.mcp_server_ref`, or at an existing connected MCP integration with `builtin_tool_config.integration_id`. 3. The platform connects to the server's URL and discovers the tools it exposes. 4. Each discovered tool becomes available to the agent's LLM. 5. When the agent invokes a tool, the platform calls the MCP server with the right credentials and returns the result. You don't write a tool definition for each remote tool. The server is the source of truth. --- ## Use a system MCP server Some common MCP servers are available as system configs. Connect and authorize the system integration, then attach that integration to the agent's `mcp_server` builtin tool. ### Connect the OAuth credential Adding the `mcp_server` tool gives the agent a place to use the MCP server. OAuth-backed servers such as Atlassian also need a connected integration credential. If the agent template creates the MCP integration for you, find it and authorize it: ```bash archagent list integrations --provider mcp:system:mcp-atlassian archagent authorize integration ``` Or create and authorize the integration directly before attaching it to a tool: ```bash archagent create integration \ --provider mcp:system:mcp-atlassian \ --auth-type oauth \ --org archagent authorize integration ``` Use the owner scope that matches how the credential should be shared: `--org` for an organization-scoped Atlassian connection, `--agent` for one agent, or `--user` for a personal connection. Then copy the connected integration ID into the agent tool config: ```yaml tools: - tool_type: builtin builtin_tool_key: mcp_server builtin_tool_config: integration_id: status: active ``` That attaches the system Atlassian MCP server to the agent. Atlassian uses OAuth discovery at `https://mcp.atlassian.com`, so you should not configure it with `auth.atlassian.com` credentials. The platform discovers Atlassian's OAuth endpoints, completes the connect flow, and then exposes the Jira and Confluence tools returned by Atlassian's MCP server. Other system MCP servers use the same pattern: ```yaml tools: - tool_type: builtin builtin_tool_key: mcp_server builtin_tool_config: integration_id: status: active ``` --- ## Add your own MCP server For an internal or unsupported MCP server, define a separate `MCPServer` config, deploy it, then reference that config from the agent. If the server uses a static bearer token, store it as an org environment variable, then reference that variable from the config: ```bash archagent create orgenvvar --org --key INTERNAL_MCP_TOKEN --value "" ``` ```yaml kind: MCPServer key: internal-tools name: Internal Tools url: https://mcp.example.com/mcp auth: type: bearer token: secret_env!: INTERNAL_MCP_TOKEN headers: X-Custom-Header: "value" timeout: 30000 ``` Then attach it to the agent: ```yaml tools: - tool_type: builtin builtin_tool_key: mcp_server builtin_tool_config: mcp_server_ref: internal-tools status: active ``` `mcp_server_ref` can be the MCPServer config's lookup key, config ID, public ID, or virtual path. --- ## Authentication modes MCP servers in ArchAgents support three authentication patterns. Pick the one that matches the server you're connecting to. ### Static bearer token The simplest option. Use it when the server accepts a long-lived API key or personal access token. First create an org-scoped environment variable for the token: ```bash archagent create orgenvvar --org --key INTERNAL_MCP_TOKEN --value "" ``` Then reference that key in the MCPServer config: ```yaml auth: type: bearer token: secret_env!: INTERNAL_MCP_TOKEN ``` The value is stored as a write-only org secret and resolved when the platform makes a request to the server. For one-off configs where you intentionally need an embedded encrypted value instead of an org env-var reference, use `secret_value!`: ```bash archagent create configsecret ``` That command calls the platform encryption API and prints ciphertext scoped to the current app and org. Paste the ciphertext into `secret_value!`; do not paste the plaintext token. ### OAuth 2.0 For services that require OAuth, declare an OAuth client and the platform handles the authorize, token-exchange, and refresh flow per user. The agent picks up the right token automatically. ```yaml auth: type: oauth client: kind: OAuthClient authorize_url: https://accounts.google.com/o/oauth2/v2/auth token_url: https://oauth2.googleapis.com/token client_id: secret_value!: client_secret: secret_value!: scopes: - https://www.googleapis.com/auth/calendar pkce: true ``` If the server publishes OAuth authorization-server metadata or supports dynamic client registration, you can omit the client block and give the platform the authorization server to discover. Servers that publish a `.well-known/oauth-authorization-server` endpoint work this way. ```yaml auth: type: oauth authorization_server: https://mcp.atlassian.com ``` Atlassian MCP uses this discovery-based pattern. ### Script-based auth For service-account flows or anything else that needs custom logic to mint a token, point the auth at a script. The script runs at request time and must return a bearer token string. ```yaml auth: type: bearer client: kind: ScriptAuthClient script: | let jwt = import("jwt") let http = import("requests") let claims = { iss: $.client_email, scope: $.scope, aud: "https://oauth2.googleapis.com/token", iat: datetime.unix(), exp: datetime.unix() + 3600 } let signed = unwrap(jwt.sign(claims, $.private_key, "RS256")) let resp = unwrap(http.post("https://oauth2.googleapis.com/token", { body: "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" + signed, headers: {"Content-Type": "application/x-www-form-urlencoded"} })) resp.body.access_token data: client_email: secret_value!: private_key: secret_value!: scope: "https://www.googleapis.com/auth/cloud-platform" ``` Use the script when no built-in auth mode covers the server's flow, for example, JWT bearer assertions for Google service accounts or signed-request schemes used by older enterprise tools. --- ## Connecting to existing integrations When you already have an integration credential for a service (because you connected it through ArchAgents Portal or `archagent authorize agentinstallation`), the MCP server can reuse that credential instead of asking for tokens again. In ArchAgents Portal, open the agent's tool configuration, choose **MCP server**, and pick the existing integration from the picker. ArchAgents Portal wires the connection and shows the discovered tools without you copying tokens around. This is the cleanest setup for servers like GitHub, Slack, or Google services where the integration credential already exists for other purposes. --- ## Other fields ```yaml kind: MCPServer name: my-tools url: https://mcp.example.com/mcp auth: type: bearer token: secret_value!: headers: X-Custom-Header: "value" timeout: 30000 ``` | Field | Purpose | |-------|---------| | `name` | Human-readable identifier shown in logs and the portal | | `url` | The MCP server endpoint URL | | `auth` | One of the three authentication modes above | | `headers` | Additional HTTP headers attached to every request | | `timeout` | Request timeout in milliseconds (default: 30000) | `name` and `url` are required. Everything else is optional. --- ## Where MCP fits with other tool kinds MCP is one of several tool kinds the platform supports: | Tool kind | When to use | |-----------|-------------| | **Builtin** | The platform already provides the capability (search, knowledge, memory, computer use) | | **Custom (script or workflow)** | You need to call your own product logic from the agent | | **MCP server** | You want a third-party tool server's full capability without defining each tool | You can mix them on the same agent. An agent can have a builtin search tool, a custom workflow-backed validation tool, and one or more MCP servers, all available at the same time. --- ## Reviewing the discovered tools After deploying an agent that uses MCP servers, inspect what the platform discovered: ```bash archagent setup ``` Then invoke embed inside your coding agent: ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` The MCP-provided tools appear in the same list as builtin and custom tools. Each entry shows the tool name and a one-line description provided by the server. This is the same operator workflow as for any other tool. See [Tools](/docs/build-agents/tools) for the full embed pattern. --- ## Best practices 1. **One MCP server per coherent capability set.** Don't bundle unrelated tool surfaces into a single server. 2. **Encrypt all credentials with `secret_value!`.** Never paste plain tokens into config YAML. 3. **Prefer integration-backed credentials over static tokens** when the service already has an ArchAgents integration. 4. **Review the discovered tool list before activation**: the LLM will see every tool the server exposes, including ones you may not want it to call. 5. **Set sensible timeouts.** A slow MCP server stalls every agent message that reaches for one of its tools. --- ## Where to go next 1. [Tools](/docs/build-agents/tools): the underlying tool model and embed loop. 2. [Extensions & Integrations](/docs/more/extensions-integrations): the broader external-system surface. 3. [Field Guards](/docs/build-agents/field-guards): validate what an agent does with tool results before they reach the user. 4. [Scripts](/docs/build-agents/scripts): for the script-based auth mode and custom token minting. --- ### Secrets URL: https://latest.docs.archagents.com/docs/operate-agents/secrets Summary: Per-agent environment variables. API keys, webhook secrets, and other credentials a single agent needs to call out to its tools. ## Overview Secrets are per-agent environment variables. One agent gets exactly the credential it needs (a Stripe API key, a webhook signing secret, a third-party token), and no other agent in the same project can read it. A secret is a `(key, value, description)` triple scoped to one agent. The platform encrypts the value at rest and never returns it to a client after you save it. The only path back to the value is the agent itself, at runtime, through the tools it's calling. That isolation is the point. One agent's credential is one agent's credential, by the platform's design, not by convention. Use secrets to: - give one agent access to a credential another agent in the same project doesn't need - rotate a value without redeploying the agent - keep API keys out of `agent.yaml` and routine source For project-wide configuration shared across every agent, use workspace environment variables instead. --- ## When to use secrets vs other primitives | Need | Use | |------|-----| | Per-agent API key (Stripe, Twilio, custom service) | **Secrets** (this page) | | Per-agent OAuth token to GitHub or Slack | [Installations](/docs/operate-agents/installations) | | Org-wide Slack bot or GitHub App | [Org-wide integrations](/docs/operate-agents/installations#org-wide-integrations-configure-once-bind-per-agent) | | Project-wide config used by every agent | workspace environment variables | The simplest test: one agent needs the value, the value is sensitive, it belongs in Secrets. --- ## Security model Three guarantees the platform makes: 1. **Write-only.** Once you save a value, the platform never returns it to a client. The list view shows a masked preview (`****1234`) so you can confirm which credential is which without exposing cleartext. 2. **Per-agent scope.** Secrets are owned by one agent. Other agents in the same project, including ones owned by the same user, have no read path. 3. **Modify gate.** Only the agent's owner or an org admin can list, create, update, or delete secrets. The portal hides the section from anyone else; the API returns `403`. To verify a value, rotate the secret and re-paste it. The platform never returns plaintext after creation. That's the property that protects you. --- ## Manage in the portal Open the agent detail page and click the **Secrets** tab. [Diagram: Agent Secrets tab listing environment variable keys with masked values] From there: - **Add secret**: opens a modal with `Key`, `Value`, and optional `Description` fields. Values type into a password input that browsers won't autofill or save. - **Edit**: replaces the value or updates the description on an existing secret. The current value is never pre-filled, because the platform doesn't have it in plaintext to show you. - **Delete**: type-to-confirm removal. Removal takes effect immediately for any agent run that starts after the delete returns. The list shows the key, the masked value, the description, and when it was last updated. If the Secrets tab isn't on an agent you're viewing, you're not the agent's owner and not an org admin. The agent's owner or an admin can add the secret for you. --- ## Manage from the CLI The CLI commands take `--agent ` for the create/list paths and the secret's own ID for describe/update/delete: ```bash # list secrets attached to an agent (values come back masked) archagent list agentenvvars --agent # create one archagent create agentenvvar \ --agent \ --key STRIPE_API_KEY \ --value sk_live_... \ --description "Live Stripe key for Customer Success Helper" # rotate the value (description stays as-is unless you pass it too) archagent update agentenvvar --value sk_live_rotated_... # update only the description archagent update agentenvvar --description "Rotated 2026-05-05" # inspect one secret archagent describe agentenvvar # remove archagent delete agentenvvar ``` `describe` returns the cleartext value only when the caller is the agent's owner or an org admin invoking the platform-level read endpoint. The list view always returns masked previews, regardless of caller. --- ## Use a secret from an agent The platform surfaces secrets to the agent at runtime as environment variables. The key you set in the portal or CLI is the variable name the agent's tools see. For example, after creating `STRIPE_API_KEY` on an agent, a script tool reads it from its process environment the same way it reads any other env var: ```typescript const stripeKey = process.env.STRIPE_API_KEY; ``` You don't declare the secret in `agent.yaml`. The platform resolves it by ID at run time, so you rotate or replace the value without redeploying the agent definition. --- ## A concrete example Customer Success Helper needs to look up a Stripe customer to answer a support question. No other agent in your project needs the Stripe key. The flow: 1. Create the secret on the helper agent only: ```bash archagent create agentenvvar \ --agent \ --key STRIPE_API_KEY \ --value sk_live_... \ --description "Read-only restricted key for support lookups" ``` 2. Confirm it's there with the masked value: ```bash archagent list agentenvvars --agent ``` 3. The agent's Stripe-lookup tool reads `process.env.STRIPE_API_KEY` and goes about its business. 4. When the key rotates 90 days later, run `update`, no redeploy: ```bash archagent update agentenvvar --value sk_live_new_... ``` A second agent in the same project that doesn't have its own Stripe secret has no access. It can't see the key, can't list it, can't call out with it. --- ## Best practices 1. **Restrict the credential before you store it.** Use the narrowest scopes that still let the agent do its job: a read-only Stripe key for lookups, a channel-restricted Slack token, a single-repo GitHub PAT. The platform isolates per-agent; restricted scopes shrink the blast radius further. 2. **Use the description field.** The next operator (or future you) needs to know what a key is for and whether it's safe to rotate. `Live Stripe key for support lookups, rotated 2026-05-05` is the kind of description that pays for itself the first time someone audits an agent. 3. **Rotate on suspicion.** A value that might have leaked is a value to rotate. Reset it at the provider, then `update agentenvvar --value `. Pasting the original back wastes the rotation. 4. **Keep secret values out of `agent.yaml`.** Reference the *idea* of the secret in agent docs or comments if it helps a reader. The actual value lives only in Secrets. 5. **Audit by listing.** `archagent list agentenvvars --agent ` is the cheapest read on what credentials an agent currently carries. Run it before sharing an agent across teams. --- ## Where to go next 1. Read [Installations](/docs/operate-agents/installations) when the credential you need is a managed OAuth token (GitHub, Slack) rather than a raw API key. 2. Read [Tools](/docs/build-agents/tools) for how the agent invokes external systems with these credentials. 3. Read [Portal](/docs/operate-agents/portal) for the broader operator workflow that the Secrets tab fits into. --- ### Skills URL: https://latest.docs.archagents.com/docs/build-agents/skills Summary: Create reusable skill packages, inspect the files behind them, and install linked skills into Claude, Codex, or Cursor through a reviewed embed workflow. ## Overview Skills are reusable packages that carry instructions, files, and supporting material a coding agent can use. They matter in ArchAgents because they bridge two worlds: - the remote agent definition in the platform - the local coding environment where developers and coding agents actually work That bridge is what makes skills more than documentation. They can become part of the day-to-day developer loop. The skill reuse model A skill can be defined once, linked to an agent, then installed into the local coding harness through an embed session. [Diagram: Diagram showing a reusable skill being authored, linked to an agent, and installed into a local coding harness through an embed session] --- ## A concrete example Suppose Company A has an `incident-review` skill that helps engineers diagnose rollout failures: - which logs to inspect first - how to search the right troubleshooting corpus - what to post back into the shared rollout thread Company A links that skill to its `Platform Support Agent`. Then a developer or coding agent can: 1. embed the support agent 2. list linked skills 3. install the incident-review skill into Claude or Codex 4. use the same operational guidance locally while debugging the live issue That's the cross-company debug loop in practice, once Company A has approved the operator access for the incident. --- ## Create and inspect skills List all reusable skills: ```bash archagent list skills archagent describe skill ``` Create one directly: ```bash archagent create skill \ -n "Incident Review" \ -d "Checklist and steps for rollout incident diagnosis" \ -s incident-review \ --file ./skills/incident-review/SKILL.md ``` You can also inspect and manage the files behind a skill: ```bash archagent describe skillfile incident-review SKILL.md archagent create skillfile incident-review references/checklist.md --file ./references/checklist.md archagent update skillfile incident-review SKILL.md --file ./skills/incident-review/SKILL.md ``` ### SKILL.md frontmatter A skill's identity lives in the YAML frontmatter at the top of its `SKILL.md`. Three fields matter: - **`lookup_key`**: the canonical slug. This is the identifier you use everywhere: `describe skill `, local skill install workflows, `create skillfile …`. Frontmatter wins if it disagrees with the directory name. - **`name`**: the human-readable display name shown in listings and the portal. - **`description`**: one-liner used for discoverability. ```markdown --- name: Incident Review description: Checklist and steps for rollout incident diagnosis. lookup_key: incident-review --- # Incident Review Instructions start here... ``` SKILL.md is the marker for a skill bundle. Any files in the same directory or its subdirectories (such as `references/checklist.md`) become children of the skill and travel with it on deploy and sync. A skill is not just a name. It is a versioned bundle of files that can actually guide work. --- ## Manage skills as configs Skills are a [Config](/docs/build-agents/configs) kind. That means you can keep them in your repo alongside agents, workflows, and scripts, and ship the whole bundle with one command. A typical layout: ```text configs/ skills/ incident-review/ SKILL.md references/ checklist.md ``` The CLI discovers each skill from its `SKILL.md` marker and treats the surrounding files as children of that skill bundle. Identity comes from the `lookup_key` in frontmatter (or the directory name if frontmatter is omitted), so renaming the directory does not break references. Push reviewed changes: ```bash archagent deploy configs ``` Pull the live state into local files: ```bash archagent sync configs ``` The `deploy configs` and `sync configs` flow keeps the local files and the live skill bundle in step, the same way it does for the rest of your project. --- ## Link skills to agents Creating or deploying a skill creates the reusable skill config. Agents do not load that config until you link it to the agent and give the agent the builtin skills tool. For config-driven agents, include both pieces in the `AgentTemplate`: ```yaml tools: - tool_type: builtin builtin_tool_key: skills status: active skills: - config_ref: incident-review status: active ``` Run `deploy configs` first when the skill lives locally, then deploy the agent template. The `config_ref` should match the skill's `lookup_key`. For an already-created agent, link the skill config directly: ```bash archagent describe skill incident-review archagent create agentskill --agent --config archagent create agenttool --agent --kind builtin --builtin-tool-key skills ``` At runtime, the builtin `skills` tool exposes `get_skill`, which loads the linked skill's `SKILL.md` and any supporting files the skill asks for. --- ## Inspect which skills are linked to an agent There are two layers to understand: - the reusable skill definitions - the links from those skills into a specific agent Inspect the links like this: ```bash archagent list agentskills --agent ``` This is the loop for confirming exactly which skills the live agent currently carries. --- ## Install a linked skill into your coding harness This is where skills stop being passive documentation. ### What a skill package actually contains A skill is anchored by `SKILL.md` and can include supporting files beside it. Teams often keep: - `SKILL.md` for the main operating instructions - references or checklists under subpaths such as `references/` - any other supporting text files the local coding workflow needs The question is not "What is the full abstract schema?" It is "What files does this skill bundle carry, and are they the right ones for the job?" You can inspect that directly: ```bash archagent describe skill archagent describe skillfile SKILL.md ``` If the embed workflow shows a linked skill id, use that exact returned id when installing the skill. Install the local plugin from your terminal: ```bash archagent setup ``` Then invoke embed inside your coding agent: ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` That gives the local coding agent access to the same operational skill package the live agent carries. This is a trust boundary: - inspect the linked skill before installing it - install only the package you actually need - be especially careful in cross-company workflows, where the skill content originates from another company's live agent definition For enterprise use, the safe default is: inspect first, install second. --- ## Update skills carefully Skills are part of the real developer workflow, so small changes can matter. ```bash archagent update skill incident-review \ -d "Updated checklist for rollout incident diagnosis" \ --file ./skills/incident-review/SKILL.md ``` If a skill changes upstream and you are already embedding the agent, refresh the local state from the Claude Code or Codex embed workflow. That keeps the local install aligned with the latest linked skill state. --- ## Best practices Good skills are: - narrow enough to explain in one sentence - concrete enough to help a developer do real work - versioned like real operational assets - attached to the agents that need them - reviewed before they are installed into a local coding harness Keep skills focused. The best ones are small enough to review in a sitting and clear enough to guide real work. --- ## Where to go next 1. Read [Embed](/docs/operate-agents/embed) for the local operating loop. 2. Read [Tools](/docs/build-agents/tools) for the action surface skills often help developers use correctly. 3. Read [Samples](/docs/build-agents/samples) for end-to-end product playbooks. --- ### Installations URL: https://latest.docs.archagents.com/docs/operate-agents/installations Summary: Attach outside systems and capabilities to an agent, inspect their state, and understand what needs attention before they become useful. ## Overview An installation is how an agent picks up an outside capability. GitHub access, a Slack workspace, a knowledge-base connector, a long-term memory store: each one is an installation attached to the agent. The installation tells you four things: - what's attached - whether it's connected - what state it's in - what to do next if it isn't usable yet When something an agent should be able to do isn't working, the installation is the first place to look. Its status tells you what's missing. ### What one installation enables A single installation can enable several things at once. Installing a GitHub App, for example, gives the agent: - **Tools**: the GitHub builtin tools (open PR, comment on issue, read file) become available as agent tools - **Knowledge**: the repositories the app is installed on become available as knowledge sources the agent can index and search - **Credentials**: a scoped token the agent uses for API calls, managed and refreshed by the platform That is why installations sit upstream of both [Tools](/docs/build-agents/tools) and [Knowledge](/docs/build-agents/knowledge): one attachment, multiple capabilities. When a GitHub-backed agent can't find a repo, the first place to look is whether the GitHub App installation is active, not the knowledge source directly. The installation lifecycle An installation starts as an attachment, moves through setup state, and only then becomes something the agent can reliably use. [Diagram: Diagram showing an agent installation moving from kind selection to setup to active state with status details] --- ## A concrete example Suppose Company A's support agent needs access to a site or provider-backed integration so it can help Company B diagnose a broken onboarding flow. The operator path is: 1. inspect the available installation kinds 2. create the installation on the right agent 3. inspect its current state 4. follow the next action if setup is incomplete 5. activate it when it is ready This is a real lifecycle, not just one create command. --- ## Available installation kinds | Kind | What it connects | |------|-----------------| | `memory/long-term` | Persistent agent memory | | `archastro/thread` | Thread context and history | | `integration/github` | GitHub personal OAuth (repo access, issues, PRs) | | `enablement/github_app` | GitHub App (org-wide repo access, bot identity for PR reviews) | | `integration/slack` | One person's Slack account; the agent reads and acts as that person | | `enablement/slack_bot` | The agent joins a workspace as its own bot; reads and posts as the bot | | `web/site` | Website content for knowledge indexing | `list agentinstallationkinds` is the source of truth for what's available in your workspace. Kinds vary by workspace and can change over time, so always check before scripting: ```bash archagent list agentinstallationkinds ``` --- ## Inspect available kinds Before you attach anything, inspect the kinds the platform supports for the current workspace: ```bash archagent list agentinstallationkinds ``` This is where you discover what categories are actually available instead of guessing from screenshots or old examples. --- ## Create an installation Create one for an agent: ```bash archagent create agentinstallation \ --agent \ --kind web/site \ --config '{"url":"https://status.example.com"}' ``` `web/site` here is a literal installation kind value, not a path. Different apps expose different kinds, so always start with `list agentinstallationkinds` before you script one. Another installation kind may require provider-specific config instead. The exact input depends on the kind. Installations are attached to agents explicitly. They are not ambient platform magic. --- ## Inspect installation state After creation, inspect it directly: ```bash archagent list agentinstallations --agent archagent describe agentinstallation ``` This is the command loop you use to answer: - what state is this installation in? - is there a next action? - is there a provider-specific connect path? - did setup fail? That information is much more actionable than vague "integration isn't working" reports. --- ## Activate or remove it Some kinds auto-activate on create and start working immediately. Kinds like `web/site`, `web/links`, `archastro/thread`, and `memory/long-term` don't need an explicit activate step. They move directly to `active` when you create them. Kinds that require external authorization (GitHub, Slack) stay in `pending` until you complete the OAuth connect flow, then activate: ```bash archagent activate agentinstallation ``` `activate` is idempotent. Running it on an already-active installation is a no-op, so scripts that call it unconditionally after create stay safe. If you no longer need an installation: ```bash archagent delete agentinstallation ``` The explicit lifecycle keeps debugging and review straightforward. There's no hidden state to chase. --- ## Org-wide integrations: configure once, bind per agent Per-agent OAuth installations attach a credential to a single agent. Slack Bot and GitHub App use a different model: an org admin creates one shared org-level integration, then each agent that should use it gets an `enablement/*` installation that binds to that shared integration. The important distinction: - `integration/github` is personal GitHub OAuth for one agent. - `enablement/github_app` is not a GitHub installation flow by itself. It is an agent-level binding to an existing shared `github_app` integration. - `enablement/slack_bot` works the same way for the shared Slack bot. For Slack specifically, follow [Slack integrations](/docs/integrations/slack) for the complete workspace-install, agent-enablement, channel-binding, and reply-thread tutorials. For agent setup, prefer the installation kind (`integration/github`) over a standalone user-scoped integration record. `create integration --provider github --user ` creates a generic integration row; it does not attach GitHub access to an agent by itself. For GitHub App specifically, the org-level setup must be completed by someone who has both permission to administer the GitHub App installation in GitHub and permission to configure org integrations in ArchAgents. A user who can manage the target agent can create the agent binding, but cannot create the shared org integration unless they also have org integration permissions. Where to enable it: - Sign in to [archagents.com](https://archagents.com) as an org admin - Open **Settings → Integrations** under **Org settings** - Click **Enable** on the Slack or GitHub card and complete the OAuth flow Behavior: - The OAuth callback persists a system-owned integration record scoped to your org. - The enablement binding resolves shared integrations in the target agent's org. Create or choose the agent in the intended org's team/user context before adding `enablement/github_app`. - Agents do not receive the shared credential automatically. Add the matching enablement installation to each agent that should use it: ```bash archagent create agentinstallation \ --agent \ --kind enablement/github_app ``` - When exactly one matching shared integration exists for the agent's org, the enablement installation auto-binds and moves to `active`. - If it stays `pending` with `next_action: configure_shared_integration`, the shared org integration is missing, not visible to you, or ambiguous. Have an org admin finish the org integration flow first. If multiple matching shared integrations exist, list them and bind the one you want explicitly: ```bash archagent list integrations --provider github_app --auth-type app_installation --org archagent create agentinstallation \ --agent \ --kind enablement/github_app \ --shared-integration ``` - Do not pass GitHub's numeric `installation_id` in the `--config` for `enablement/github_app`. That config creates only the agent binding; it does not create the required shared `github_app` integration record. - If direct integration creation such as `create integration --provider github_app --auth-type app_installation --org ` returns `Forbidden`, your current session is not allowed to configure org-level app installations. Use an org admin account or the org integrations page described above. - Per-agent OAuth integrations such as `integration/github` continue to work in parallel. Use them when an agent should use a personal GitHub token instead of the org GitHub App. When to use which: | Situation | Pick | |-----------|------| | Agent A and agent B should both post to the same Slack workspace | Org-wide | | Agent A operates in workspace X, agent B in workspace Y | Per-agent | | Multiple agents should use the same GitHub App installation | Org-wide shared integration plus `enablement/github_app` on each agent | | You're shipping an agent that needs its own personal GitHub credential | Per-agent `integration/github` | Only the Slack Bot and GitHub App providers support the org-wide path today. Slack user OAuth and GitHub personal OAuth (`integration/slack`, `integration/github`) stay per-agent. --- ## How installations relate to knowledge and tools Installations are the upstream attachment surface behind: - knowledge connections - provider-backed integrations - certain tool capabilities They matter even when a developer thinks they're "really working on knowledge" or "really working on tools." The installation's status tells you whether the underlying attachment is healthy before you debug anything higher level. --- ## Best practices Good installation workflows follow four rules: 1. inspect kinds before creating 2. attach only what the agent actually needs 3. check status and next action before blaming the model 4. activate only when the setup is clearly ready Predictable installations make agents easier to trust as you scale up. --- ## Where to go next 1. Read [Knowledge](/docs/build-agents/knowledge) for the source and ingestion layer above installations. 2. Read [Tools](/docs/build-agents/tools) for action surfaces the agent can operate once attachments are ready. 3. Read [Webhooks](/docs/operate-agents/webhooks) when you need the lighter-weight path for an external system to push events into the platform without a full integration. 4. Read [Portal](/docs/operate-agents/portal) for the visual operator workflow around setup and review. --- ### Models & Providers URL: https://latest.docs.archagents.com/docs/build-agents/models Summary: Choose the model and provider for your agents and judges. Anthropic, OpenAI, Google Gemini, xAI, or any of the 300+ models available through OpenRouter. ## Overview ArchAgents is provider-neutral. The platform talks to multiple LLM providers natively and routes every model call through one consistent interface. You pick the right model for the job, and the platform handles the provider-specific differences underneath. This matters in three concrete places: - **An agent's primary model**: the model the agent uses when it reasons, replies, and calls tools. - **An `LLMJudge` field guard's model**: the model that grades a structured response against a policy. See [Field Guards](/docs/build-agents/field-guards). - **Cross-vendor verification**: stack two judges using different vendors so a prompt injection that exploits one model's quirks still has to defeat the other. See [Stacking judges across vendors](/docs/build-agents/field-guards#stacking-judges-across-vendors). The same model string format works in every place models are configured. --- ## Supported providers | Provider | Prefix | What it gives you | |---|---|---| | **Anthropic** | `anthropic/` | Claude models called directly against Anthropic's API | | **OpenAI** | `openai/` | GPT models called directly against OpenAI's API | | **Google Gemini** | `google/` | Gemini models called directly against Google's API | | **Meta** | `meta/` | Muse Spark models called directly against Meta's Model API | | **xAI** | `xai/` | Grok models called directly against xAI's API | | **OpenRouter** | `openrouter/` | 300+ models from many vendors through a single OpenRouter account, including Anthropic, OpenAI, Google, and others | Direct provider integrations are useful when you have a relationship with a specific vendor or want to use vendor-specific features. OpenRouter is useful when you want one billing relationship that covers many models, or when you want to try a model that doesn't have a direct integration. --- ## Model strings Every place that takes a model accepts a `/` string. ```yaml # Direct provider format model: anthropic/ model: openai/ model: google/ model: xai/ # Through OpenRouter (always three segments) model: openrouter// ``` The format is the same regardless of where you configure it: the LLM judge, the agent's primary model, or any future surface that takes a model. Use the discovery flow below to fill in the exact `` for the provider you want. Do not shorten OpenRouter IDs to `openrouter/` or invent nearby aliases such as `openrouter/anthropic/claude-next`. --- ## Finding the model string you need The suggested IDs below are valid starting points. If you are using the recommended default, no discovery command is needed. Use the live catalogue only when you need a different provider, model family, capability, or latency/cost profile: ```bash archagent help models archagent list aimodels ``` The strings the platform accepts always follow the `/` shape: `anthropic/...`, `openai/...`, `google/...`, `xai/...`, or `openrouter//` for OpenRouter's broader catalogue. Good starting values: | Use case | Model | |---|---| | Recommended agent default | `openrouter/anthropic/claude-sonnet-latest` | | Direct Anthropic | `anthropic/claude-sonnet-latest` | | Direct OpenAI | `openai/gpt-5-latest` | | Direct Google | `google/gemini-flash-latest` | | Direct xAI | `xai/grok-latest` | | OpenRouter OpenAI | `openrouter/openai/gpt-5-latest` | | OpenRouter Google | `openrouter/google/gemini-flash-latest` | Once you have a valid model string, drop it into a `model:` field anywhere it's accepted (LLMJudge field guards, agent creation, etc.). --- ## Where you can set the model ### On a field guard (`LLMJudge`) Override the judge model on a per-guard basis: ```yaml field_guards: - kind: LLMJudge fields: ["summary"] model: anthropic/ prompt: > Does this text reveal internal infrastructure details? on_match: reject ``` Leave `model` unset to use the platform's default judge model. See [Field Guards](/docs/build-agents/field-guards) for the full guard model. ### On an agent For config-driven agents, set the model in the `AgentTemplate`: ```yaml kind: AgentTemplate agent_key: support-agent name: Support Agent model: openrouter/anthropic/claude-sonnet-latest identity: | You help users resolve support issues. ``` Set the agent's primary model when you create or update the agent with the `-m, --model` flag: ```bash # Create with a specific model archagent create agent -n "Support Agent" -k support-agent \ -i "You are a helpful support agent." \ -m openrouter/anthropic/claude-sonnet-latest # Update an existing agent's model archagent update agent --model openai/gpt-5-latest ``` Run `archagent create agent --help` or `archagent update agent --help` to see the full flag set. Run `archagent list aimodels` for currently valid model strings. ### Platform default If you don't set a model on either the agent or the judge, the platform uses a sensible default. You don't need to think about model selection until you have a reason to override. Start with the default and pick a specific model when capability, latency, or vendor diversity actually matter. --- ## Cross-vendor verification The strongest reason to care about which model runs where is the **cross-vendor verification pattern**: stack two `LLMJudge` field guards on the same field, with one using `anthropic/...` and the other using `openai/...` (or any two different vendors). ```yaml field_guards: - kind: LLMJudge fields: ["summary"] model: anthropic/ prompt: on_match: reject - kind: LLMJudge fields: ["summary"] model: openai/ prompt: on_match: reject ``` Both judges run. Both must pass. A prompt injection that exploits one model's quirks still has to defeat a model with completely different training data and different blind spots. This is the single most defensible field-guard pattern. See [Stacking judges across vendors](/docs/build-agents/field-guards#stacking-judges-across-vendors) for the full explanation and the trade-offs. --- ## Choosing a model The right model depends on the work, not on which one is newest. A few practical guides: - **For conversational agent replies**: pick a strong general-purpose model from any vendor. Latency matters because the user is waiting. - **For deterministic structured-output policies in an LLM judge**: pick a fast model with strong instruction-following. The judge is asked one yes/no question; you don't need the largest model on the menu. - **For cross-vendor judge stacking**: pick two models from different vendors regardless of relative capability. The diversity is the defense, not the individual capability of either model. - **For long-context work**: context window varies a lot within a single vendor's lineup. Pick the model that gives you the headroom you need; use `archagent list aimodels` when you want the current supported IDs. - **For tools that depend on a vendor-specific capability**: pick the vendor that supports it. Some models have native search; some have native thinking; some have native image output. When in doubt, leave the platform default in place and override only the model where you have a concrete reason. --- ## Where to go next 1. [Field Guards](/docs/build-agents/field-guards): where the LLM judge model is configured. 2. [Cross-Company Privacy](/docs/collaborate/cross-company-privacy): the broader defense-in-depth model that cross-vendor verification fits into. 3. [Agents](/docs/build-agents/agents): the agent model that uses the primary model. --- ### Computer Use URL: https://latest.docs.archagents.com/docs/operate-agents/computer-use Summary: Computer use lets an agent act through a managed execution environment when simple tool calls are not enough. ## Overview Computer use gives an agent a managed place to carry out interactive tasks. Use it when the agent needs to do work that looks more like operating a computer than calling one simple tool. The mental model is: - a normal tool call is one clean action - computer use is a small working environment where the agent can carry out a sequence of visible steps That breadth is the value, and it's also why computer use carries more operational weight than ordinary tools. --- ## A concrete example Imagine an agent needs to walk through a browser-based admin interface that does not have one clean API. Computer use can help the agent: 1. open the interface 2. navigate through the relevant screens 3. gather or enter the needed information 4. report the result back into the thread or workflow That is different from a simple "call this endpoint" tool. It is closer to giving the agent a controlled workstation for a narrow task. From the CLI, the operational loop looks like this: ```bash archagent list agentcomputers --agent archagent create agentcomputer --agent -n "ops-workstation" archagent describe agentcomputer archagent refresh agentcomputer archagent exec agentcomputer -c "pwd" ``` That gives you a real workflow for provisioning, checking readiness, and validating the environment before you ask the agent to rely on it. --- ## What computer use is not Computer use is not the default way agents should operate. It is the wrong choice when: - one explicit API or tool call would do - the task can be expressed as a clean workflow step - the task is sensitive enough that a human should do it directly The point is not to make agents click around for the sake of it. The point is to give them a controlled way to handle the cases where interactive work is genuinely necessary. --- ## When it helps Computer use is a good fit when an agent needs to: - work through a multi-step interface - inspect or manipulate a system that is not exposed as one clean API - carry out a guided operational task It is not the right first choice for everything. If a smaller, clearer tool will do, use the smaller tool. If you can express the action as one explicit tool, do that first. Reach for computer use when the work is genuinely interactive. ### Built-in tools Agents can use computers during conversations through four built-in tools: ### `computer_exec` Execute a shell command on the agent's computer. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `command` | string | Yes | Shell command to execute | | `working_directory` | string | No | Working directory | Returns `stdout`, `exit_code`, and `status`. ### `computer_write_file` Write content to a file on the computer. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `path` | string | Yes | Absolute file path | | `content` | string | Yes | File content to write | ### `computer_read_file` Read the contents of a file from the computer. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `path` | string | Yes | Absolute file path | ### `use_claude` Start an asynchronous Claude Code run on the agent's computer. This tool creates a durable agent session and returns immediately with a session ID instead of blocking the current turn. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `prompt` | string | Yes | Prompt to send to Claude | | `working_directory` | string | No | Working directory for the run | | `name` | string | No | Optional label for the durable Claude session | | `model` | string | No | Claude model to use. Accepts Claude Code aliases (`opus`, `sonnet`, `haiku`) or a full model ID (e.g. `claude-opus-4-7`). Defaults to `opus`. | `use_claude` only resolves when the agent has computer use, an active GitHub installation, and sub-agents enabled. At execution time the session injects GitHub and Claude credentials when available, runs Claude non-interactively on the VM, and reports the result back through the existing durable sub-agent/session flow. ### Tool resolution When an agent uses computer tools, the platform automatically routes the request to a ready computer associated with that agent. --- ## Safety guidelines Computer use increases agent capability, so it needs stronger guardrails. Before enabling computer use, be clear on: - what environment the agent can use - what actions are allowed - what approvals exist - how a human can review the result From the CLI: - inspect the computer status before using it - keep the environment narrow - destroy computers you no longer need --- ## Best practices 1. Start with narrow tasks. 2. Keep the environment limited to the work at hand. 3. Put sensitive actions behind explicit approval. 4. Review outputs and logs regularly. 5. Prefer simpler tools when they cover the task. --- ### Webhooks URL: https://latest.docs.archagents.com/docs/operate-agents/webhooks Summary: Receive events from external systems and turn them into agent reactions or fresh context, with signing-secret verification and an inspectable event history. ## Overview Webhooks let external systems push events into ArchAgents so your agents can react to them. Use a webhook when: - a third-party product (GitHub, Slack, or your own service) emits an event you want an agent to act on - you want incoming payloads to become indexed context the agent can search later - the trigger lives outside the platform and you would otherwise have to poll for it The platform verifies every incoming request with a signing secret you set, so webhooks fail closed if a payload is unsigned, expired, or forged. From external event to agent reaction An external system POSTs to your webhook URL. The platform verifies the signature, dispatches to the routines or context source you wired up, and records the event for inspection. [Diagram: Diagram showing an external system posting to a ArchAgents webhook URL, the signing-secret verification, dispatch to a routine or context source, and the recorded event history] --- ## Create a webhook ```bash archagent create webhook \ --provider github \ --signing-secret \ --enabled ``` Three fields drive the behavior: | Option | What it does | |--------|--------------| | `--provider ` | Use a built-in provider's verification and event shape. The platform knows how to verify GitHub's `X-Hub-Signature-256` and Slack's `X-Slack-Signature` headers. | | `--lookup-key ` | For generic webhooks. Use any service you control, set the lookup key to something you can reference later (e.g. `acme-billing`). | | `--signing-secret ` | Required. The shared secret the sender uses to sign requests. Rotate it with `update webhook -s ` whenever you rotate it on the sender side. | Add `--provision-context-source` to auto-create an inbound context source connected to this webhook. Useful when the events should also become searchable context for an agent. Inspect what you have: ```bash archagent list webhooks archagent describe webhook ``` --- ## Inspect events Every incoming request is recorded. Inspect the history when you are debugging "did the webhook actually fire?": ```bash archagent list webhookevents --webhook ``` The list shows arrival time, signature verification status, the event type, and any downstream dispatch outcome. --- ## React to webhook events Once a webhook is set up, an agent reacts in one of two ways: - **Trigger a routine.** A routine with a webhook event type fires whenever a matching event arrives. This is the path for "do something when X happens upstream." - **Ingest into context.** When you create the webhook with `--provision-context-source`, payloads are also indexed as a knowledge source the agent can search later. This is the path for "make these events part of what the agent can see." Both paths can run from the same webhook. Use the routine for the immediate reaction, and the context source for the long-term knowledge. --- ## Update or delete ```bash archagent update webhook --enabled false archagent update webhook --signing-secret archagent delete webhook ``` Disabling is reversible; deleting is not. Disable first if you suspect a misbehaving sender: events stop dispatching but the configuration stays in place for inspection. --- ## Security and signing A webhook without a working signing secret is effectively a public POST endpoint, so every webhook in ArchAgents requires one and verifies it on every request. Failed verifications are recorded in the event list with an explicit failure reason; they never reach a routine or context source. Rotate the signing secret on the sender first, then update the webhook on the platform side. Until both sides agree, requests will be rejected, which is the correct fail-closed behavior. --- ## Where to go next 1. [Installations](/docs/operate-agents/installations): for OAuth-backed integrations (GitHub App, Slack, Gmail) that go beyond a single webhook URL. 2. [Knowledge](/docs/build-agents/knowledge): when webhook payloads should also become indexed context. 3. [Agents](/docs/build-agents/agents): for the routine model that dispatches off webhook events. --- ### Extensions & Integrations URL: https://latest.docs.archagents.com/docs/more/extensions-integrations Summary: Connect agents to outside systems through built-in integrations, custom tools, MCP servers, webhooks, and scripts. ## Overview ArchAgents agents connect to outside systems in five ways: | Method | What it does | When to use it | |--------|-------------|----------------| | **Built-in integrations** | Connect to GitHub and Slack with OAuth or app installations | You need an agent to read from or act in a known service | | **Custom tools** | Define your own tool backed by a script, workflow, or HTTP endpoint | You need the agent to call your own APIs or business logic | | **MCP servers** | Connect to any remote MCP-compatible tool server | You want to use tools from the MCP ecosystem | | **Webhooks** | Receive inbound events from external systems | You need to trigger agent behavior from outside ArchAgents | | **Scripts** | Write custom logic with HTTP calls, JWT auth, and data transformation | You need to call any API with full control over the request | These methods compose. An agent can use built-in GitHub integration for knowledge, a custom tool for your billing API, and a script-based routine that calls a third-party webhook — all at the same time. --- ## Built-in integrations ArchAgents has native support for connecting to common services. Each integration handles authentication, token refresh, and data access. Start with the [Integrations overview](/docs/integrations/overview) for the credential and installation model. For Slack, follow the complete [Slack setup and channel-routing tutorials](/docs/integrations/slack). | Integration | What it provides | |-------------|-----------------| | **GitHub** (OAuth) | Personal-account repo access, issues, PRs — for knowledge indexing and code context | | **GitHub App** | Org-wide repo access with a bot identity — for PR reviews, automated comments | | **Slack** (OAuth) | User-level Slack workspace access | | **Slack Bot** | Post messages to channels, read channel history | Two install models: - **Per-agent OAuth** — one credential, one agent. Best when each agent needs its own scope or a separate workspace. ```bash archagent create agentinstallation --agent --kind integration/github archagent authorize agentinstallation archagent activate agentinstallation ``` - **Shared app installation** (Slack Bot and GitHub App only) — an org admin first creates the shared org integration, then each agent gets an `enablement/*` binding to that shared integration. ```bash # After the org-level GitHub App integration exists: archagent create agentinstallation --agent --kind enablement/github_app ``` `enablement/github_app` is only the binding step. Passing GitHub's numeric `installation_id` in the installation config does not create the required shared org integration; a pending install with `next_action: configure_shared_integration` means the org-level prerequisite still needs to be completed or selected. If multiple shared integrations exist, pass `--shared-integration ` when creating the enablement installation. See [Org-wide integrations](/docs/operate-agents/installations#org-wide-integrations-configure-once-bind-per-agent) for the full setup path and permission requirements. Once connected, the agent can use the integration through its builtin tools (e.g. `integrations`, `knowledge_search`) and script bindings. See [Installations](/docs/operate-agents/installations) for the full list of available kinds and the setup lifecycle. --- ## Custom tools When the agent needs to call your own APIs or run business-specific logic, create a custom tool. Custom tools can be backed by: | Handler | How it works | |---------|-------------| | **Script** | Runs an ArchAgents script that can make HTTP calls, transform data, and return results | | **Workflow** | Triggers a multi-step workflow with branching, approvals, and external calls | | **HTTP endpoint** | Calls an external URL directly with the tool arguments as the request body | Define custom tools in an AgentTemplate: ```yaml tools: - tool_type: custom name: lookup_order description: Look up a customer order by ID parameters: type: object properties: order_id: type: string handler_type: script config_ref: order-lookup-script ``` Or create them directly: ```bash archagent create agenttool --agent \ --kind custom \ --name "lookup_order" \ --description "Look up a customer order by ID" ``` See [Tools](/docs/build-agents/tools) for the full tool model and embed workflow. --- ## MCP servers ArchAgents supports connecting to remote [MCP (Model Context Protocol)](https://modelcontextprotocol.io) servers. This lets agents use any tool from the MCP ecosystem (Atlassian, Stripe, Linear, Sentry, Notion, or your own internal tool servers) without writing a custom tool for each one. You attach an MCP server through the builtin `mcp_server` tool: ```yaml tools: - tool_type: builtin builtin_tool_key: mcp_server builtin_tool_config: integration_id: status: active ``` The platform connects to the server, discovers its tools, and exposes them to the agent automatically. Use `integration_id` for system MCP servers such as Atlassian, or define your own `MCPServer` config and reference it from the tool with `mcp_server_ref`. Authentication supports static bearer tokens, full OAuth 2.0 flows (with discovery and dynamic client registration), and script-based auth for service-account patterns. See [MCP Servers](/docs/build-agents/mcp) for the full setup, all auth modes, and how MCP servers compose with the rest of the tool model. --- ## Webhooks Inbound webhooks let external systems trigger agent behavior. When ArchAgents receives a webhook, it can: - trigger an automation - start a workflow - ingest data into knowledge Webhooks are configured from the CLI, or in the developer portal under **Dashboard -> Apps -> _your app_ -> Webhooks**. Each webhook gets a unique URL that external systems can POST to. --- ## Scripts with HTTP access For full control over external API calls, use scripts with the `requests` namespace: ``` let http = import("requests") let jwt = import("jwt") let dt = import("datetime") // Sign a JWT for service account auth let token = unwrap(jwt.sign({ iss: env.CLIENT_EMAIL, scope: "https://www.googleapis.com/auth/cloud-platform", aud: "https://oauth2.googleapis.com/token", iat: dt.unix(), exp: dt.unix() + 3600 }, env.PRIVATE_KEY, "RS256")) // Exchange for access token let resp = unwrap(http.post("https://oauth2.googleapis.com/token", { headers: {"Content-Type": "application/x-www-form-urlencoded"}, body: "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" + token })) resp.body.access_token ``` Scripts can call any HTTP API — REST, GraphQL, webhooks, OAuth token exchanges. Combined with `env` variables for secrets, this gives you full programmatic access to any external service. See [Scripts](/docs/build-agents/scripts) and the [Script Language Reference](/docs/build-agents/script-reference) for the full language. --- ## Choosing the right approach | You want to... | Use | |----------------|-----| | Connect to GitHub or Slack | Built-in integration | | Call your own product API from an agent | Custom tool | | Use tools from the MCP ecosystem | MCP server | | Trigger agent work from an external system | Webhook | | Call any HTTP API with full control | Script with `requests` | Start with built-in integrations for supported services. Use custom tools or scripts when you need something specific to your business. --- ### Field Guards URL: https://latest.docs.archagents.com/docs/build-agents/field-guards Summary: Privacy by construction: run deterministic checks and cross-vendor LLM judges on every agent response before it ships. ## Overview Field guards enforce response policies on the agent itself. Every reply is checked **before it ships**. Deterministic checks (`ContainsString`, `ContainsAny`, `RegexMatch`) catch obvious leaks in milliseconds. An `LLMJudge` guard, running on a different model from the agent, catches the subtle ones. Stack multiple judges from different vendors, and a prompt injection that exploits one model's quirks still has to defeat the others. When any guard fires with `reject`, the message doesn't leave the agent. This is **privacy by construction**: the policy is part of the response schema, runs every time, and can't be bypassed by prompt engineering alone. There's no wrapper agent to maintain, no post-hoc scanner that flags violations after the reader already saw them, no relay thread that might forget to enforce the rule. One config block on the agent's `AgentMessageSchema` replaces the fragile "sanitizer agent wrapping another agent" pattern. ### What field guards defend against | Risk | How field guards help | |---|---| | **Accidental data leak**: agent pastes internal runbook content, ticket IDs, or source code into a customer-facing response | Regex and substring guards catch structural patterns; an LLM judge catches nuanced leaks the agent phrases creatively | | **Prompt injection**: a hostile user tricks the agent into ignoring its instructions | Guards run after the LLM and cannot be disabled by anything the LLM produces. Cross-vendor judges compound the defense: an injection must defeat every judge, not just the first one | | **Model regression**: a model upgrade changes the agent's tone or sharing behavior | Guards run every time regardless of model version; regressions that drift past prompt-level guidance still get caught by the same policy | | **Subtle content policy drift**: the agent used to follow the "summarize only, don't paste" rule; today's conversation pushed it to paste anyway | A schema-level policy is durable and reproducible across deploys | ### When to reach for field guards Use field guards when: - the agent's output will be read by a customer, partner, or external system and certain things must never appear - prompt-level guidance is not a sufficient guarantee ("don't leak internal ticket numbers" works only until it doesn't) - you need a durable, reproducible policy that survives prompt tweaks, model upgrades, and new agent versions - you want a second opinion from a different LLM vendor on every sensitive response Field guards are not a replacement for careful prompt design. They're an additional layer that runs every time, regardless of how the LLM behaves. See [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for how field guards fit into the broader defense-in-depth model. --- ## Before and after ### The leak scenario A customer asks a support agent for help with a webhook failure. The agent's knowledge sources include both customer-facing docs and an internal runbook. Without field guards, the agent's response schema constrains the **shape** of the reply (a `summary` and a `next_action` string) but says nothing about the **content**. The agent, being helpful, reaches into the internal runbook, finds the escalation path, and writes: ```json { "summary": "This looks like the INC-48219 retry issue. Ping @sarah.k on the #webhooks-internal channel and tell her to run the runbook/internal/webhook-retry-fix steps 3-7.", "next_action": "Escalate to Sarah" } ``` The response matches the schema. The response ships. The customer now has an internal ticket ID, an employee handle, an internal channel name, and a runbook path. None of which they should have seen. ### The same schema with field guards ```yaml kind: AgentMessageSchema id: support-reply schema: type: object properties: summary: { type: string } next_action: { type: string } required: [summary, next_action] field_guards: # 1. Fast: block known internal markers - kind: ContainsAny fields: ["*"] values: - "runbook/internal" - "#webhooks-internal" - "[INTERNAL]" on_match: reject message: "Response contains an internal-only marker" # 2. Fast: redact internal ticket IDs - kind: RegexMatch fields: ["*"] pattern: "\\b(INC|TKT|BUG)-\\d{4,}\\b" on_match: redact message: "Redacted internal ticket ID" # 3. Nuanced: LLM judge catches subtle internal detail - kind: LLMJudge fields: ["summary", "next_action"] prompt: > Does this text reveal internal infrastructure details, employee names, internal chat channels, or specific escalation steps that a customer should not see? on_match: reject message: "LLM judge flagged internal detail" ``` The same agent producing the same output now hits `ContainsAny` on `runbook/internal` and `#webhooks-internal`. The response is rejected before it reaches the regex. If the agent had phrased it more subtly (no literal marker, no ticket ID pattern), the LLM judge would have caught it at the third layer. The customer never sees any of it. That's four lines of YAML policy replacing a wrapper-agent pattern that would otherwise take dozens of files and still be bypassable. --- ## How they run 1. The agent generates a structured response that conforms to its `AgentMessageSchema`. 2. The platform extracts the resolved field values. 3. **Synchronous guards** run first: the deterministic checks (`ContainsString`, `ContainsAny`, `RegexMatch`). 4. If all synchronous guards pass, **asynchronous guards** run: the LLM-based judge (`LLMJudge`). 5. Each guard returns a **violation** with one of three actions: `reject`, `redact`, or `warn`. 6. The platform applies the strictest action: a `reject` blocks the response, `redact` rewrites the offending field, `warn` lets the response through but records the violation. Synchronous guards run before the judge so deterministic rules can short-circuit the response before any LLM evaluation is needed. --- ## On-match actions Every guard has an `on_match` setting that controls what happens when the guard fires. | Action | Behavior | |--------|----------| | `reject` | Block the response. The agent's output is discarded and the violation is surfaced. | | `redact` | Replace the offending field value with `[REDACTED]` and let the rest of the response through. | | `warn` | Allow the response unchanged but record the violation for review. | Default is `reject`. Use `redact` when the rest of the output is still useful without the sensitive piece, and `warn` when you want the activity feed entry but not a behavior change. --- ## Field paths Every guard targets one or more `fields` in the structured response. Field paths support: - **Plain field names**: `summary`, `email`, `notes` - **Dot notation for nested objects**: `customer.address.zip` - **Array wildcards**: `contacts[*].email`, `attachments[*].url` - **Match-everything wildcard**: `"*"` for all string fields in the response ```yaml fields: ["summary"] fields: ["customer.address.zip"] fields: ["contacts[*].email", "contacts[*].phone"] fields: ["*"] ``` `"*"` is the most permissive. Use it when you want a guard that applies to every string the agent might emit, without enumerating field names. --- ## Synchronous guards These run first and are deterministic. They catch the obvious cases without invoking another model. ### ContainsString Block, redact, or warn when a field contains a specific substring. ```yaml - kind: ContainsString fields: ["*"] value: "CONFIDENTIAL" case_sensitive: false on_match: redact message: "Response contains a confidential marker" ``` | Field | Purpose | |-------|---------| | `value` | The substring to search for (required) | | `case_sensitive` | Default `false` | | `on_match` | `reject`, `redact`, or `warn` (default `reject`) | | `message` | Human-readable explanation surfaced in violations | Use this for clear keyword bans: internal classification markers, forbidden product names, single-string detection of sensitive terms. ### ContainsAny Same as `ContainsString` but checks against a list of terms. The first match wins. ```yaml - kind: ContainsAny fields: ["summary", "details"] values: - "internal-only" - "do not share" - "draft - not for partners" case_sensitive: false on_match: reject message: "Response contains text marked as not for sharing" ``` Use this for compact deny-lists of sensitive terms or markers. Easier to maintain than several `ContainsString` guards with the same action. ### RegexMatch For patterns that aren't fixed substrings: credit cards, social security numbers, internal ticket formats, email addresses you want to redact. ```yaml - kind: RegexMatch fields: ["*"] pattern: "\\b\\d{3}-\\d{2}-\\d{4}\\b" on_match: redact message: "Response contains SSN-like pattern" ``` Use regex when the policy is shape-based, not term-based. Combine with `redact` for content-cleaning patterns and `reject` for hard fails like API keys. --- ## LLM judge (asynchronous) Deterministic guards can't catch nuanced policy violations: tone, sensitivity, factual claims, brand voice, "is this PII?" against context. For those, use an LLM judge. ```yaml - kind: LLMJudge fields: ["summary", "details"] prompt: > Does this text contain personally identifiable information such as social security numbers, credit card numbers, or full home addresses? on_match: reject message: "LLM judge flagged PII in response" ``` | Field | Purpose | |-------|---------| | `prompt` | The rule the judge evaluates the field value against (required) | | `model` | Override the default judge model when you need a specific one | | `on_match` | Default `reject` | | `message` | Human-readable explanation surfaced in violations | The judge receives the field value and your prompt, then returns a fixed `{pass, reason}` structured output. The structured shape is enforced; you control the prompt, not the response format. The judge uses a sensible default model out of the box. Override the `model` field with any string from the [supported model list](/docs/build-agents/models) when you need a specific provider or version. See [Models & Providers](/docs/build-agents/models) for the full set of providers and how to discover the current model catalogue. ### When to use the judge | Situation | Guard | |-----------|-------| | "Is the literal string `CONFIDENTIAL` here?" | `ContainsString` | | "Is there an email address?" | `RegexMatch` | | "Is this text condescending toward the customer?" | `LLMJudge` | | "Does this leak any PII for any reasonable definition of PII?" | `LLMJudge` | | "Does this match our brand voice?" | `LLMJudge` | | "Is this factually consistent with the source documents?" | `LLMJudge` | Reach for the judge when the policy needs human-style understanding. Use synchronous guards for everything that fits a substring or regex. ### Prompt design The judge prompt should ask one yes/no question. The judge returns `{pass: true | false, reason: "..."}`, and the platform decides what to do based on `pass`. Good judge prompts: - ask exactly one thing - describe what should fail, not what should pass - give one or two short examples of the failure case - avoid open-ended judgment ("is this good?"); be specific Bad judge prompts: - ask multiple questions in one - mix policy goals (PII, tone, factual accuracy) into one prompt - depend on context the judge doesn't have If you have multiple policies, use multiple `LLMJudge` guards rather than one omnibus prompt. ### When to reach for a judge vs. a synchronous guard Judges add latency: the agent's reply waits for the judge before reaching the user. Synchronous guards run first so deterministic rules can short-circuit before a judge fires. Use a synchronous guard when the policy expresses cleanly as a string, list, or regex; reach for a judge when nuance is required. --- ## Stacking judges across vendors The single most defensible field-guard pattern is stacking two or more `LLMJudge` guards that use **different model vendors** on the same field. Every judge runs; every judge must pass. A prompt injection or jailbreak that exploits one model's quirks still has to defeat a completely different model to get the response through. ```yaml field_guards: # Judge A. Anthropic - kind: LLMJudge fields: ["summary"] model: anthropic/ prompt: > Does this text reveal internal infrastructure details, employee names, or specific escalation paths that only the company's own support team should know? on_match: reject message: "Anthropic judge flagged internal detail" # Judge B. OpenAI, same question - kind: LLMJudge fields: ["summary"] model: openai/ prompt: > Does this text reveal internal infrastructure details, employee names, or specific escalation paths that only the company's own support team should know? on_match: reject message: "OpenAI judge flagged internal detail" ``` Why this compounds defense: - **Different training data, different blind spots.** A jailbreak that relies on a specific Claude quirk doesn't automatically work on GPT-4o, and vice versa. An attacker has to find an exploit that works on both. - **Independent failure modes.** If one vendor has a regression that makes the judge too lenient on a particular phrasing, the other vendor's judge is unaffected. - **One config block, not two sanitizer agents.** The alternative (running the response through a second agent before sending it) is more code, more latency, more failure modes, and more prompt engineering to maintain. Stacking judges is a few extra lines of YAML. You can stack more than two vendors if the policy warrants it. You can also use the same vendor with different prompts (one judge for PII, one for tone), but the cross-vendor case is the one that defeats model-specific attacks. **Trade-off:** every additional judge is another LLM call on every response, which adds latency. Use synchronous guards to catch obvious violations first, then cross-vendor judges for the small set of responses where the policy actually needs nuanced evaluation. --- ## A complete example Four layers of defense, fastest first, most nuanced last, with a cross-vendor judge at the top of the judgment layer: ```yaml kind: AgentMessageSchema id: customer-summary schema: type: object properties: summary: type: string sentiment: type: string enum: [positive, neutral, negative] next_action: type: string required: [summary, sentiment] field_guards: # Layer 1. Fast: block obvious markers - kind: ContainsAny fields: ["summary", "next_action"] values: ["INTERNAL", "DO NOT SHARE", "DRAFT"] on_match: reject message: "Response contains internal-only marker" # Layer 2. Fast: redact PII patterns - kind: RegexMatch fields: ["*"] pattern: "\\b\\d{3}-\\d{2}-\\d{4}\\b" on_match: redact message: "Redacted SSN-like pattern" # Layer 3. Nuanced: Anthropic judge on PII - kind: LLMJudge fields: ["summary"] model: anthropic/ prompt: > Does this summary mention any specific person's full name, home address, or financial account number? on_match: reject message: "Anthropic judge flagged personal information" # Layer 4. Cross-vendor second opinion - kind: LLMJudge fields: ["summary"] model: openai/ prompt: > Does this summary mention any specific person's full name, home address, or financial account number? on_match: reject message: "OpenAI judge flagged personal information" ``` This stack enforces four layers, in order: hard markers, regex patterns, a nuanced Anthropic judgment, and a cross-vendor second opinion. Each layer catches what the previous one missed. Each synchronous guard is free once the response is produced. Each judge runs only if all earlier layers passed. The agent cannot ship a response that any of the four layers flags. The practical effect: a prompt injection that successfully bypasses the agent's instructions still has to produce output that (a) contains no obvious markers, (b) matches no PII regex, (c) fools the Anthropic judge, and (d) fools the OpenAI judge, which has different training data and different blind spots. That's a much harder target than "convince one LLM to ignore its system prompt." --- ## Where to attach guards Field guards live on an `AgentMessageSchema` config. The schema is referenced from an agent routine that produces structured output: ```yaml routines: - name: customer-triage handler_type: preset preset_name: do_task preset_config: structured_message_template_refs: - "#/schemas/customer-summary" status: active ``` When the routine runs, the agent generates output matching the schema, and every field guard in the schema runs against the result. See [Structured Output](/docs/build-agents/structured-output) for the schema model. --- ## Reviewing violations Field guard violations show up in the [activity feed](/docs/operate-agents/activity-feed) attached to the routine run that produced them. Each violation entry includes: - which guard fired - which field path matched - the human-readable `message` you set on the guard - the action that was applied (`reject`, `redact`, or `warn`) When you're triaging a `warn`-level guard or tuning a new policy, the activity feed is the place to start. --- ## Best practices 1. **Start with synchronous guards.** They catch the obvious cases without invoking another model. Add the LLM judge only when the policy needs interpretation. 2. **Use `redact` for content cleanup, `reject` for hard policy fails.** Reserve `warn` for tuning a new guard before you trust it. 3. **One judge prompt, one policy.** Don't pile multiple goals into a single LLM judge, split them. 4. **Stack judges across vendors for the policies that matter most.** For high-stakes fields, configure two `LLMJudge` guards with the same prompt but different model vendors (e.g. `anthropic/...` and `openai/...`). An attack that exploits one model's quirks still has to defeat the other. See [Stacking judges across vendors](#stacking-judges-across-vendors). 5. **Pin a specific judge model when your policy must be reproducible.** Override the default when you need bit-for-bit consistency across runs. 6. **Test guards with real outputs, not synthetic inputs.** Run the agent in a sandbox with realistic prompts and inspect the resulting activity feed entries. Tune until violations match your intent. 7. **Layer with other safety patterns.** Field guards are one layer. See [Cross-Company Privacy](/docs/collaborate/cross-company-privacy) for the full stack. --- ## Where to go next 1. [Structured Output](/docs/build-agents/structured-output): the schema field guards run on. 2. [Cross-Company Privacy](/docs/collaborate/cross-company-privacy): defense for sensitive collaborations. 3. [Activity Feed](/docs/operate-agents/activity-feed): where guard violations are recorded. 4. [Agents](/docs/build-agents/agents): how routines connect to message schemas. --- ### Key-Value Storage URL: https://latest.docs.archagents.com/docs/build-agents/kv-storage Summary: Small, structured state that an agent or workspace needs to remember between runs, without sending it through an LLM turn. ## Overview Key-value storage is for the small, structured state your agent or workspace needs to keep between runs. Use it when something is true and worth remembering, but does not belong in conversational memory or in a config file: - a dedupe marker so the agent does not act twice on the same input - a counter, a last-seen timestamp, or a "last deploy SHA" - a short flag that another script needs to read on the next run - the result of a one-off lookup you do not want to repeat Key-value storage is deterministic. You read what you wrote. There is no LLM in the loop. Memory, key-value storage, and configs Each home for state has its own job. The shape of what you are storing tells you which one to reach for. [Diagram: Diagram comparing three places state can live in ArchAgents: agent memory for durable facts, key-value storage for small structural state, and configs for source-controlled setup] --- ## When to use it (and when not to) | Use key-value storage for | Use [Agent Memory](/docs/operate-agents/agent-memory) for | |---------------------------|------------------------------------------------------------| | Structural state, flags, counters, IDs, hashes | Durable facts the agent should know across conversations | | Logic that needs an exact value back | Soft context like preferences or recurring project facts | | Cheap, fast reads inside scripts | Information the agent uses to behave more consistently | If the value is something a teammate would expect the agent to "remember," it probably belongs in memory. If it is something the agent's own logic needs to look up to do its job, it belongs in key-value storage. For project-wide configuration that should be reviewable in source control, reach for [Configs](/docs/build-agents/configs) instead. --- ## In scripts: the `storage` namespace Inside a script, the `storage` namespace gives you read and write access to the calling agent's own bucket. ```text let storage = import("storage") // Has this PR already been reviewed? let existing = storage.get("pr_" + prNumber.toString() + "_reviewed") if existing.ok { return "SKIP" } // Remember the deploy we just acted on unwrap(storage.set("last_deploy_sha", commitSha)) // Mark a transient flag that expires unwrap(storage.set("alert_sent", "true", { remember_until: "1 day" })) ``` The available functions are: | Function | Returns | Notes | |----------|---------|-------| | `storage.get(key)` | `Result` with `{key, value}` or not-found | Use for full reads | | `storage.set(key, value)` | `Result` with `{key, value}` | Upsert. Adds or replaces | | `storage.set(key, value, { remember_until })` | `Result` with `{key, value}` | TTL form. See remember_until below | | `storage.exists(key)` | `Result` with boolean | Cheaper than `get` when you only need a yes/no | | `storage.delete(key)` | `Result` with `{key, value}` | Removes the entry | | `storage.list()` | `Result` with `{entries, count}` | Returns this agent's full bucket | `remember_until` accepts `"1 hour"`, `"1 day"`, `"7 days"`, `"14 days"` (default), `"30 days"`, `"forever"`, or an ISO 8601 timestamp. Values without an explicit `remember_until` use the default of 14 days. The script must be running in an agent context (the viewer needs to be an agent). Routine handlers and workflow-attached scripts already meet that requirement. --- ## In the developer portal: browse and edit The developer portal exposes the KV store under **Dashboard -> Apps -> _your app_ -> Storage -> Key-Value**. From there you can: - search by key prefix or by user - inspect a value, including its expiry - create, edit, or delete entries by hand Reach for it when you're debugging: to confirm a flag was actually set, clear a stuck dedupe marker, or seed a value for a test. --- ## From the SDK The developer SDK exposes the same store programmatically, useful when your workspace needs to read or write entries on behalf of a specific user. ``` import { ArchAstro } from "@archastro/developer-platform-sdk"; const archastro = new ArchAstro({ secretKey: process.env.ARCHASTRO_SECRET_KEY }); // List entries for one user const page = await archastro.kv.list(appId, { user: userId }); // Read or write a single entry const entry = await archastro.kv.upsert(appId, userId, "feature_flag.beta", { value: "true" }); ``` This is the right surface when the value is set or read by your product code rather than by an agent script. --- ## A practical pattern A daily release-notification automation can use storage to make sure the agent does not double-post: 1. Each morning, the automation reads `last_announced_release` from storage. 2. If the latest release matches, the automation returns early. 3. Otherwise it posts the announcement and writes the new value back. That is the whole job: one read, one comparison, one write. The agent stays deterministic, the channel does not get spammed, and a human can inspect the value in the portal at any time. --- ## Best practices A good key-value setup is: - **specific**: keys describe what is stored, not where it came from - **bounded**: values are short, structured, and rarely larger than a few hundred bytes - **intentional**: every write has a clear reason, every read has a clear use - **reviewable**: a teammate can look at the keys in the portal and follow the agent's logic Avoid using key-value storage as a general document store or a fallback for things that should live in [Knowledge](/docs/build-agents/knowledge). The store is small on purpose. --- ## Where to go next 1. [Agent Memory](/docs/operate-agents/agent-memory): when "remember this fact" is the right framing instead of "store this value." 2. [Scripts](/docs/build-agents/scripts): the surface where most key-value reads and writes live. 3. [Configs](/docs/build-agents/configs): for setup that belongs in source control rather than a runtime store. --- ### Custom Objects URL: https://latest.docs.archagents.com/docs/build-agents/custom-objects Summary: Define your own data shapes (leads, tickets, releases, anything else) so agents can read, write, and reason about the entities your business actually cares about. ## Overview Custom objects let you give your agents typed, workspace-defined data structures. Instead of asking an agent to remember "we have leads with these fields" in its prompt, you define the shape once as a schema and then create as many instances of that shape as you need. Use custom objects when: - the agent needs to track entities specific to your business (a lead, a release, a customer account, an incident) - different runs need to read or update the same record over time - you want a queryable list of those entities, not free-form notes scattered across threads A custom object is a row of structured data. The schema describes the shape. The instances are the data the agent actually works with. --- ## Schemas first Each custom object belongs to a schema, identified by a `lookup_key`. The schema is a config: you define it once, ship it through the same `deploy configs` workflow as the rest of your project, and reference it from the agent's tools or scripts. A schema declares: - the fields the object has (name, type, required-or-not) - which fields are searchable - any defaults See [Configs](/docs/build-agents/configs) for the deploy/sync flow. The kind for these schemas is `CustomObjectSchema`, discoverable via `archagent list configkinds`. --- ## Create, read, update, delete The CLI exposes a full CRUD surface keyed by the schema: ```bash # List instances of a schema, optionally searching archagent list custom-objects --schema-key lead archagent list custom-objects --schema-key lead --search "acme" # Fetch the one instance with a specific row_key archagent list custom-objects --schema-key lead --row-key acme # Inspect one archagent describe custom-object # Create a new instance with a fields payload archagent create custom-object \ --schema-key lead \ --fields '{"company":"Acme","stage":"qualified","owner":"alice@company.com"}' # Update some fields archagent update custom-object \ --fields '{"stage":"contracted"}' # Delete archagent delete custom-object ``` Pagination follows the same pattern as the rest of the CLI: `--page`, `--page-size`, and `--all` for scripts. --- ## Owners and scoping Custom objects can be scoped to a specific user or team: - `--user `: the object is owned by one user; only that user (and admins) can manage it - `--team `: the object is owned by a team; team members can manage it - neither: the object is workspace-scoped; anyone with workspace access can manage it This matters when the same schema represents both per-user state ("my drafts") and shared state ("our leads"). Pick the owner at create time and the platform enforces access automatically. --- ## How agents work with them Agents work with custom objects from scripts. Scripts can read or write objects directly, which is useful when the logic is deterministic and you do not need the LLM in the loop. See the `agents.*` and namespace bindings in [Scripts](/docs/build-agents/scripts). Either way, the schema is the source of truth for the shape. Agents and scripts trust it, and a misshapen update is rejected before it ever lands. --- ## A practical pattern A pipeline-tracking agent uses a `lead` schema with a few fields (company, stage, owner, last_touched_at). The agent's routines: 1. Read the current pipeline at the start of each session with `list custom-objects --schema-key lead`. 2. Update the right record when something changes, one field at a time. 3. Surface a digest in the channel the team watches. Compared with keeping that state in conversational memory, custom objects make the data inspectable, queryable, and durable across handoffs. --- ## Where to go next 1. [Configs](/docs/build-agents/configs): to deploy and version-control the schemas that drive your custom objects. 2. [Tools](/docs/build-agents/tools): for the builtin and custom tool path that exposes objects to an agent in an LLM session. 3. [Key-Value Storage](/docs/build-agents/kv-storage): for small structural state that doesn't warrant a schema. --- ### CLI URL: https://latest.docs.archagents.com/docs/start-here/cli Summary: The terminal workflow for building and operating agents. ## Overview The ArchAgents CLI is the fastest way to build and operate agents from the terminal. Use it to: - sign in and connect a project - deploy agents from YAML templates - create conversations and send test messages - inspect runs, threads, tools, and knowledge - manage configs, sandboxes, and installations If you use a coding agent (Claude Code, Codex, Cursor), the CLI is the primary setup path. --- ## Fastest path If you want to get from zero to an agent you can test quickly, do this: 1. install the CLI 2. sign in 3. connect the current project with `archagent init` 4. create or deploy an agent 5. open a thread and send it a message The rest of this page expands those steps. ## How to think about the CLI Teams use the CLI in one of three ways: | Mode | What you are doing | |------|--------------------| | **First-run setup** | Link a repo and create your first testable agent | | **Daily development** | Inspect, update, and test agents, routines, threads, and sandboxes | | **Repeatable deployment** | Keep configs in files and deploy them in a reviewable way | `--json` is a global flag. Scripted examples often place it before the verb, as in `archagent --json create agent...`. The CLI loop Connect the repo, create or update the object, test it, inspect the result, then make the next change. [Diagram: Diagram showing the ArchAgents CLI loop from init to create to test to inspect to iterate] --- ## 1. Install the CLI GitHub Releases are the public distribution path for the CLI. ### macOS ```bash brew install ArchAstro/tools/archagent ``` ### Linux ```bash curl -fsSL https://archagents.com/install.sh | bash ``` ### Windows ```powershell irm https://archagents.com/install.ps1 | iex ``` If your organization doesn't allow piped installers, download the release assets from GitHub Releases and inspect them before running locally. Verify the install: ```bash archagent --help ``` ## 2. Sign in ```bash archagent auth login you@company.com archagent auth status ``` Pass your work email as a positional argument. The CLI uses it to resolve your organization's sign-in configuration (password, SSO, or SAML) before opening the browser so you land on the right sign-in flow. If your organization is on an app other than the default `agentnetwork`, add `--app `: ```bash archagent auth login you@company.com --app ``` The CLI opens a browser so you can complete sign-in and authorize the local session. Use `archagent auth logout` when you want to clear the current session. --- ## 3. Connect the current project ```bash cd my-project archagent init ``` `archagent init` connects the current directory to ArchAgents and writes an `archagent.json` file in the project root. That file tells the CLI which project and config directory the current workspace should use. In these docs, a **project** is your local linked workspace. An **app** is the ArchAgents application that workspace points at. --- ## 4. Install a starter sample (fastest) If you want a working agent in front of you in seconds, browse the curated sample catalog and install one: ```bash archagent list agentsamples archagent install agentsample ``` `install agentsample` deploys the sample's agent into the linked project and runs the steps declared in the sample's `sample.yaml`. The result is a real, editable agent, useful as a starting shape you can iterate on, not a fixed demo. Pin a version for reproducible installs (`@v0.3.2`), or pass `--name "Acme Support"` to override the default name. The agent is editable from the moment it lands; nothing about a sample install locks you into the original shape. If you'd rather author your agent from scratch, continue with the next section. --- ## 5. Create your own agent ### Repeatable setup: deploy from a template Write an `agent.yaml` in your project and deploy it in one command: ```bash archagent deploy agent agent.yaml --name "Support Agent" ``` This is the recommended path for agents you intend to keep. The template is reviewable, reusable, and keeps your agent config in version control alongside your code. Agent templates should include an explicit primary model. Start with: ```yaml model: openrouter/anthropic/claude-sonnet-latest ``` Use `archagent help models` or `archagent list aimodels` to see valid provider-specific values. ### Quick experiment: create an agent directly If you want to understand each piece individually, you can create an agent directly: ```bash archagent create agent -n "Support Agent" -k support-agent \ -i "You help users resolve billing and support problems with short, concrete answers." ``` Here `-k` sets the agent's lookup key: the key you can search for and reuse in scripts and CLI flows. The quickest proof that this is an AI agent, not just a saved object, is one direct session: ```bash archagent create agentsession --agent \ --instructions "Help a user resolve billing questions. Ask one clarifying question if needed." archagent exec agentsession \ -m "How should we handle invoice failures?" ``` If you want the agent to react automatically inside the product, add a routine: ```bash archagent create agentroutine --agent \ -n "Reply to new messages" \ -e thread.message_added \ -t script \ --script "{ handled: true }" archagent activate agentroutine ``` `thread.message_added` is the basic "new thread message arrived" event. `script` is the smallest handler type and is useful for proving the wiring before you move into richer workflow-backed behavior. New routines start in `draft`, so save the routine ID from the `create` command and activate it before you test thread traffic. That inline script still runs under the same scoped platform access rules as the agent and routine that triggered it. It is useful for small deterministic checks, not as a replacement for reviewable workflows. For anything beyond this first proof, move the logic into a proper script or workflow where you can inspect and test the input shape directly. ### Direct session versus thread The CLI exposes both because they solve different problems: - `agentsession` is the quickest direct test of the agent itself - threads and messages are the product conversation surface used over time Start with an `agentsession` when you want a quick proof. Move to threads when you want to inspect the full runtime loop with members, messages, and ongoing behavior. ## A realistic first CLI session Here is what a first CLI session looks like: 1. run `archagent init` in the repo you care about 2. create one agent with a narrow job 3. run one direct agent session and inspect the result 4. create and activate one routine that reacts to `thread.message_added` 5. create one test user and one test thread 6. send one message That's enough to confirm the day-one essentials: the project is connected, agents can be created from the terminal, the agent participates in conversations, and the loop is inspectable end to end. --- ## 6. Open a thread and send a message Create a thread that the agent owns: ```bash archagent create thread -t "Support" --owner-type agent --owner-id ``` Create or reuse a user who will send the test message: ```bash archagent create user --system-user -n "Demo User" ``` `--system-user` creates a bot-style non-login user. Use it when you need test traffic from the CLI without creating a person account. If you later need machine-to-machine auth for that identity, issue a dedicated system-user access token instead of trying to log in as a person. Those tokens are separately minted, can be listed and revoked, and are checked against the platform's system-token registry on use. Add that user to the thread: ```bash archagent create threadmember --thread --user ``` Then send a message: ```bash archagent create threadmessage --thread --user \ -c "How should we handle invoice failures?" ``` Add `--wait` when you want the CLI to stay attached and print the resulting response activity before returning. This is the shortest path to proving that the agent exists, can join a conversation, and can start doing work in that thread. --- ## What can go wrong ### The CLI is not authenticated ```text Not authenticated. Run: archagent auth login ``` Fix: ```bash archagent auth login you@company.com archagent auth status ``` ### The current repo is not linked ```text No archagent.json found. Run: archagent init ``` Fix: ```bash archagent init ``` ### The project is linked, but the token is missing ```text No token for this project. Run: archagent auth login ``` Fix: ```bash archagent auth login you@company.com ``` --- ## Common workflows ### Inspect and manage agents ```bash archagent list agents archagent describe agent archagent update agent -n "Senior Support Agent" archagent delete agent ``` Use this loop when you are tuning instructions, names, routines, or ownership and want to confirm the live object state. ### Manage conversations ```bash archagent list threads archagent describe thread archagent list threadmembers --thread archagent list threadmessages --thread archagent list threadmessages --thread --full ``` `--full` switches from the compact message table to the full conversation view. This is the quickest way to answer "what happened?" when a test did not behave the way you expected. ### Add a computer to an agent ```bash archagent list agentcomputers --agent archagent create agentcomputer --agent -n "dev" archagent describe agentcomputer ``` Reach for this when an agent needs a managed computer environment rather than only message- and workflow-based behavior. ### Operate the serious surfaces Once you move beyond a first agent, the CLI becomes an operator console for the live platform surface: ```bash # Inspect knowledge state archagent list knowledgesources archagent list knowledgeingestions --status failed # Inspect installations and tool attachments archagent list agentinstallations --agent archagent list agenttools --agent # Inspect durable memory archagent list agentworkingmemory --agent ``` The day-to-day loop for agent development: - inspect what the agent is attached to - inspect what it can use - inspect what it remembers - debug the agent's tool and skill surface before changing prompts Privileged workflows such as embed are deliberate operator actions. Use them only from the app and company context your deployment has explicitly approved. ### Set up your local coding agent If you work with Claude Code, Codex, or another local AI coding harness, the CLI can install the ArchAgents plugins for you in one step: ```bash archagent setup ``` By default this installs for the current user. Pass `--scope project` to install only inside the current repository, or `--dry-run` to preview the changes first. Use `--claude-only`, `--codex-only`, or `--cursor-only` to scope the install to a single harness. After setup, your coding agent has the ArchAgents commands and conventions available locally. This is the same loop teams use to keep their coding-agent setup consistent across machines. ### Invoke embed from the coding agent The shell CLI installs and authenticates the plugin. The embed command is typed inside your coding agent, not into your terminal. Claude Code: ```text /embed ``` Codex: ```text $embed ``` Cursor: ```text @archagents embed ``` Use the coding-agent command after `archagent setup` and a harness restart. ### Work with config files ```bash archagent sync configs archagent deploy configs mkdir -p ./tmp archagent describe configsamples workflow --to-file ./tmp/workflow.sample.yaml archagent validate configs -k workflow -f ./tmp/workflow.sample.yaml archagent describe configsamples ``` Config files become more important as the setup gets larger. If you are still exploring the product, direct `create` commands are simpler. Once you know what you want, move the stable setup into files. Read [Configs](/docs/build-agents/configs) for the full file-backed workflow. --- ## Common command groups Think of these groups in the same order you would build with ArchAgents: 1. agents 2. users and teams 3. threads and messages 4. sandboxes and automations 5. knowledge, tools, and installations 6. config files and project-level setup ### Agents ```bash archagent list agents archagent describe agent archagent create agent -n "Support Agent" archagent create agent -n "Support Agent" --model openrouter/anthropic/claude-sonnet-latest archagent update agent -n "New Name" archagent update agent --model openai/gpt-5-latest archagent delete agent ``` `--model` (short `-m`) sets the agent's primary model to any string from the [supported model list](/docs/build-agents/models). Run `archagent help models` for suggested values and `archagent list aimodels` for the current catalogue. ### Users ```bash archagent list users archagent describe user archagent create user -e alice@example.com -n "Alice" archagent create user --system-user -n "Demo User" archagent delete user ``` ### Teams ```bash archagent list teams archagent list teams --joinable archagent describe team archagent create team -n "Engineering" archagent update team -n "New Name" archagent delete team archagent join team archagent join team --agent ``` `--joinable` lists teams the current user can join through the team's access policy. This is the discovery step for cross-organization collaboration, see [Network Getting Started](/docs/collaborate/agent-network-getting-started). `archagent join team ` joins on behalf of the signed-in user, or with `--agent`, places one of your agents into the team. ### Threads ```bash archagent list threads archagent describe thread archagent create thread -t "Project thread" --user archagent create threadmember --thread --agent archagent create threadmessage --thread --user -c "Hello" ``` Use `--skip-welcome-message` on thread creation when you want the first visible message in the thread to be the one you send on purpose. Use `--wait` on `create threadmessage` when you want the CLI to stay attached for the response loop. ### Automations ```bash archagent list automations archagent describe automation archagent create automation -n "Daily Report" -t scheduled --schedule "0 8 * * *" archagent activate automation archagent pause automation archagent delete automation ``` ### Knowledge ```bash archagent list integrations archagent list knowledgesources archagent list knowledgeingestions --status failed archagent list knowledgeitems --source ``` ### Tools ```bash archagent list agenttools --agent archagent describe agenttool archagent create agenttool --agent --kind builtin --builtin-tool-key search archagent activate agenttool ``` ### Installations ```bash archagent list agentinstallationkinds archagent list agentinstallations --agent archagent create agentinstallation --agent --kind web/site --config '{"url":"https://example.com"}' archagent describe agentinstallation ``` ### Embed Install the local plugin from your terminal, then invoke embed inside your coding agent: ```bash archagent setup ``` ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` ### Skills ```bash archagent list skills archagent describe skill archagent create skill -n "Incident Review" --file ./skills/incident-review/SKILL.md archagent describe skillfile incident-review SKILL.md ``` ### Memory and routine runs ```bash archagent list agentworkingmemory --agent archagent list agentroutineruns --routine archagent list automationruns --automation ``` ### Activity feed ```bash archagent list activity archagent list activity --agent archagent list activity --kind routine_run --level error archagent describe activity archagent run activity --agent archagent run activity --org ``` `run activity` opens a live stream and prints each new entry as the platform records it. See [Activity Feed](/docs/operate-agents/activity-feed) for filters, levels, and the full kind list. ### Files and project setup ```bash archagent list files ``` Use ArchAgents Portal for domains, webhooks, and other project-level setup that does not need to live in your terminal workflow. ### Configs ```bash archagent init --enable-configs archagent list configkinds archagent sync configs archagent deploy configs archagent describe configsamples mkdir -p ./tmp archagent describe configsamples workflow --to-file ./tmp/workflow.sample.yaml archagent validate configs -k workflow -f ./tmp/workflow.sample.yaml ``` Use configs when the setup has graduated from exploration into something you want to keep in files and review like code. ### Scripts ```bash archagent validate scripts --file ./path/to/script.yaml archagent run scripts --file ./path/to/script.yaml --input '{"key": "value"}' archagent describe scriptdocs ``` ### Organizations Organization setup is handled as part of operator-managed multi-company deployment work, not as part of the normal first-run CLI path. Use [Organizations](/docs/collaborate/organizations) to understand the boundary model when your deployment includes company-specific spaces. ### Sandboxes ```bash archagent list sandboxes archagent describe sandbox archagent create sandbox -n "Staging" -s staging archagent activate sandbox archagent list sandboxmails --sandbox ``` Here `-s` sets the sandbox slug: the short unique key for that sandbox inside the app. `activate sandbox` re-authenticates with a sandbox-scoped token. Pass a sandbox ID directly (`activate sandbox `) or omit it to get an interactive selection flow. --- ## Scripting with JSON output All commands support `--json`, which makes the CLI easy to use from shell scripts and coding-agent workflows. ```bash archagent list agents --json | jq -r '.data[].id' USER_ID=$(archagent create user -e bot@example.com --system-user --json | jq -r '.id') archagent list teams --json | jq '.data[] | select(.name | contains("Eng"))' ``` Because `--json` is global, `archagent --json create user...` works too. Use whichever placement you prefer, but keep it consistent inside a script. ### Pagination and `--all` Every list command paginates. Pass `--page` and `--page-size` to walk pages by hand, or `--all` to fetch every page in one call: ```bash archagent list agents --all --json | jq -r '.data[] |.name' archagent list threads --page 2 --page-size 50 ``` `--all` is convenient for scripts that need the full set. For interactive use, the default first page plus the cursor footer is enough. --- ## Shell completion ```bash eval "$(archagent completion bash)" eval "$(archagent completion zsh)" archagent completion fish | source ``` --- ## Project files | File | Purpose | |------|---------| | `./archagent.json` | Project mapping and local CLI settings | --- ## Where to go next 1. [Getting Started](/docs/start-here/getting-started): zero-to-one install and first agent. 2. [AstroDev](/docs/start-here/astrodev): interactive coding agent TUI (`archagent astrodev`), plan mode, sessions, and headless `--print`. 3. [Astrorun](/docs/start-here/astrorun): local discovery, processing, and persisted review records for agent work (`archagent astrorun`). 4. [Use ArchAgents from your coding agent](/docs/start-here/coding-agents): Claude Code, Codex, and Cursor plugins. 5. [Embed](/docs/operate-agents/embed): step into a live agent's tools and skills from a coding agent. --- --- ### Configs URL: https://latest.docs.archagents.com/docs/build-agents/configs Summary: Move a setup you trust into files so the team can review and ship it cleanly. ## Overview Configs are the file-backed definition layer for an ArchAgents project. Use them when you have already proved a setup works and now want to: - keep it in version control - review changes before deployment - sync the live project into local files - redeploy the same shape without rebuilding it by hand - direct `create` commands are fast for exploration - `configs/` is the right home once the shape is real and worth keeping --- ## What a config actually is A config is a versioned project object stored as file content plus a virtual path. That means: - the platform still has live objects - the CLI can pull those objects into local files - your team can review and redeploy them from the repo Configs turn agent setup into reviewable code that lives in your repo alongside everything else. The CLI exposes two related-but-different surfaces, both verb-first: - **Direct config commands** (`archagent describe config`, `archagent validate configs`, `archagent list configs`) work with live config objects directly. Use them when you're debugging or inspecting one specific config. - **The local file-backed loop** (`archagent sync configs`, `archagent deploy configs`) manages a local `configs/` directory you can edit, review in source control, and push back. Use it for repeatable, reviewable changes. Teams use both. They inspect live objects when they need to debug, then use `configs/` when they want changes they can review and redeploy. --- ## The basic config loop Start by creating the local config directory: ```bash archagent init --enable-configs ``` Then inspect the kinds the project supports: ```bash archagent list configkinds archagent describe configsamples agent archagent describe configsamples workflow ``` Use those samples to understand the file shape before you edit anything. When the sample is an `AgentTemplate`, keep or add its `model:` field. Start with `openrouter/anthropic/claude-sonnet-latest` and use `archagent help models` when you need another provider. When you want to pull the current project state into local files: ```bash archagent sync configs ``` When you are ready to push reviewed changes back: ```bash archagent deploy configs ``` If you keep generated or scratch files inside `configs/` that should not ship, add an `.aaignore` file at the root of the directory. The deploy step honors it the same way Git honors `.gitignore`: ```text # configs/.aaignore **/_generated/ *.draft.yaml ``` If you need to inspect a single live config while you are debugging: ```bash archagent list configs --kind workflow archagent describe config ``` `describe config` shows both the config metadata and its full content. That is often the fastest way to answer "what is the platform actually holding right now?" before you sync anything locally. --- ## Validate before you deploy The safest pattern is: 1. generate or edit the config locally 2. validate the content 3. deploy only after it is readable and intentional For example: ```bash mkdir -p ./tmp archagent describe configsamples workflow --to-file ./tmp/workflow.sample.yaml archagent validate configs -k workflow -f ./tmp/workflow.sample.yaml ``` That is especially useful when a coding agent is generating config content and you want a quick sanity check before deployment. When the config already exists on the server, validate the file and then inspect the live object before you deploy: ```bash archagent describe config ``` That keeps the local file and the live platform object in the same review loop, the `describe` output includes the full content alongside the metadata. --- ## When to stay with direct commands Stay with direct commands when you are: - proving the first agent loop - testing one routine - poking at the data model - learning the CLI surface Move to configs when you are: - keeping an agent or workflow for the long term - collaborating through code review - deploying the same setup more than once - managing a project with several stable objects --- ## A realistic team pattern Teams follow this sequence: 1. create one agent directly 2. test it with an `agentsession` 3. attach the first routine or workflow 4. once the shape feels right, run `configs init` 5. sync the live setup into `configs/` 6. review future changes as files instead of recreating objects manually That gives you fast learning first, then repeatability. ### A workflow-specific example Suppose the team builds a workflow from a config sample, then iterates on it. The sequence is: 1. generate a sample with `archagent describe configsamples workflow` 2. edit the workflow file locally 3. validate before deploy 4. run `archagent deploy configs` 5. review the result in the portal for a visual overview 6. iterate by editing the file and redeploying That pattern keeps the CLI and source control as the primary creation path while the portal provides the visual review layer. --- ## Best practices Five rules for working with configs: 1. prove the setup live before you freeze it into files 2. keep paths and kinds readable 3. validate generated content before deploy 4. prefer reviewed file changes over repeated ad hoc recreation 5. use sync to keep the local view honest --- ## Where to go next 1. Read [CLI](/docs/start-here/cli) for the full terminal workflow. 2. Read [Samples](/docs/build-agents/samples) for end-to-end examples that move from direct commands into config files. 3. Read [Workflows](/docs/build-agents/workflows) when the file-backed object you are managing is a process definition. --- ### For Coding Agents URL: https://latest.docs.archagents.com/docs/start-here/for-coding-agents Summary: The machine-readable version of Getting Started for Claude Code, Codex, Cursor, and similar AI coding tools. > **Human?** This page is written for the coding agent at your terminal. If you're looking for the human walkthrough, see [Getting Started](/docs/start-here/getting-started). ## Overview You're being asked to get ArchAgents working in this repo and put the first agent live. The whole flow is four terminal commands plus one embed command inside this chat. Stay on that path unless the user asks for something more elaborate. --- ## Quick prompt If the user hasn't pasted instructions yet, the canonical version is: ```text Get ArchAgents working in this repo and put my first agent live. 1) Install the ArchAgents CLI. macOS: brew install ArchAstro/tools/archagent. Linux/Windows: see https://docs.archagents.com/docs/start-here/getting-started. 2) Run these in order, asking me for anything missing: archagent setup archagent auth login archagent install agentsample archastro-onboarding 3) Once the install finishes, the starter agent is live. Tell me, then invite me to embed: Claude Code → /embed Codex → $embed Cursor → @archagents embed 4) After I embed, ask me what I actually want to build. Help me scope it, author the template, and deploy it. The reference surface is https://docs.archagents.com/llms-full.txt. ``` --- ## What the four commands actually do | Command | What it does | |---|---| | `archagent setup` | Installs the ArchAgents plugin into Claude Code, Codex, and Cursor. Idempotent. | | `archagent auth login ` | Opens a browser to complete sign-in and writes a session token for the CLI. | | `archagent install agentsample archastro-onboarding` | Deploys a real, editable starter agent into the user's org. When it returns, the agent is live. | | `/embed` (or harness equivalent) | Inside the coding-agent chat. Picks up the live agent's tools and skills locally. | After these four, the user has an agent they can talk to. Anything else (custom routines, knowledge sources, integrations) is iteration on top. --- ## Where to find what | Resource | URL | |---|---| | Documentation | `https://docs.archagents.com` | | ArchAgents Portal | `https://archagents.com` | | LLM index (short) | `https://docs.archagents.com/llms.txt` | | LLM index (extended) | `https://docs.archagents.com/llms-full.txt` | Treat these as canonical. Don't invent alternate hosts or endpoint roots. --- ## Environment variables Check for these before non-interactive operations. Ask the user if any are missing rather than guessing. | Variable | When you need it | Purpose | |---|---|---| | `ARCHASTRO_SECRET_KEY` | CI or non-interactive use | Authentication when browser sign-in isn't available | | `ARCHASTRO_APP_ID` | Linking to a specific existing project | When the repo should point at an app that already exists | --- ## If the user wants to author an agent template by hand Most users won't. The default path is `archagent install agentsample ` followed by tweaks inside their coding agent. If they specifically ask for a from-scratch template, here's a minimal valid shape. Deploy it with `archagent deploy agent agent.yaml`. ```yaml kind: AgentTemplate agent_key: support-agent name: Support Agent model: openrouter/anthropic/claude-sonnet-latest identity: | You help users resolve support and billing problems with short, concrete answers. tools: - tool_type: builtin builtin_tool_key: search status: active - tool_type: builtin builtin_tool_key: knowledge_search status: active routines: - name: Respond in conversations handler_type: preset preset_name: participate event_type: thread.session.join event_config: thread.session.join: filters: {} status: active installations: - install_type: memory/long-term config: {} ``` Keep the `model:` field when authoring AgentTemplate YAML. Start with `openrouter/anthropic/claude-sonnet-latest` unless the user requests another provider; accepted formats are `anthropic/`, `openai/`, `google/`, `xai/`, and `openrouter//`. Use `archagent help models` or `archagent list aimodels` before inventing a model string. For everything else, see [Agents](/docs/build-agents/agents) and use `archagent --help` to discover flags. --- ## Names you'll use in conversation | Term | What it means | |---|---| | **Agent** | The long-lived AI identity the user creates and manages | | **Routine** | An event handler on an agent: when X happens, do Y | | **Automation** | An event handler on the project (not tied to one agent) | | **Tool** | An action the agent can take | | **Knowledge** | Information the agent can retrieve | | **Thread** | The conversation surface where people and agents exchange messages | | **Network** | A shared space where agents from two companies can collaborate | | **Embed** | A local session where this coding agent operates as the live agent | --- ## Rules 1. Check required env vars before write operations. Ask for what's missing. 2. The fastest path to a working agent is the install-a-sample path. Don't author yaml unless the user asks. 3. When authoring AgentTemplate YAML, include `model:`. Prefer `openrouter/anthropic/claude-sonnet-latest` unless the user asks for another model. 4. Use `archagent --help`, `archagent --help`, and `archagent help models` to discover flags and model IDs. Don't guess. 5. Use [`llms-full.txt`](https://docs.archagents.com/llms-full.txt) before scraping rendered pages. 6. Don't put secret keys in client-side code or commit them. 7. Don't add scaffolding the user didn't ask for. 8. When you're done, summarize what was created in plain language: what got deployed, where it lives, and the one command to test it again. --- ### Samples URL: https://latest.docs.archagents.com/docs/build-agents/samples Summary: End-to-end playbooks that combine the portal, Network, and CLI into realistic developer workflows. ## Overview Each section below is an end-to-end playbook you can copy. Not isolated commands; a full developer flow that takes you from a fresh repo to a working agent doing the actual job. These samples are CLI-first. If you want the shortest setup path, start with [Getting Started](/docs/start-here/getting-started). Each sample walks through: - what you are building - what to set up (CLI, coding agent, or portal) - what you run in the CLI - what you should expect to see The CLI still does most of the work. The portal and Network show up where the product actually expects them. Jump to: [Sample 1](#sample-1-create-one-working-support-agent) | [Sample 2](#sample-2-move-the-setup-into-reviewable-config) | [Sample 3](#sample-3-run-a-scheduled-workflow-with-a-script-in-the-middle) | [Sample 4](#sample-4-test-a-notification-flow-in-a-sandbox) | [Sample 5](#sample-5-coordinate-a-rollout-across-two-companies) | [Sample 6](#sample-6-debug-a-cross-company-integration-by-embedding-the-support-agent) | [Sample 7](#sample-7-deploy-a-real-agent-from-a-template) --- ## How to use these samples A few practical notes before you start: 1. Every `create` command returns an ID. Save it before you move to the next step. 2. If you want to script the sequence, add `--json` and capture `.id` with `jq`. Example: ```bash agent_id=$(archagent --json create agent -n "Support Agent" -k support-agent \ -i "You help users solve billing and support problems clearly." | jq -r '.id') ``` If you prefer to work more manually, you can also run `archagent describe ...` or `archagent list ...` after each step and copy the ID you need. These flags appear several times below: - `--skip-welcome-message` keeps the thread creation step quiet so your test begins with the message you send on purpose - `--wait` keeps the CLI attached long enough to show the result of the message or action you just triggered - `--json` is a global CLI flag, so these examples place it before the verb: `archagent --json create ...` --- ## Sample 1: Create one working support agent ### What you are building A single agent inside one company that can answer one test request, then pick up a routine for automatic follow-up behavior. This is the smallest slice of ArchAgents that still shows the full loop: - one project - one agent - one live session - one thread - one incoming message ### Prerequisites 1. The CLI is installed and authenticated (`archagent auth login you@company.com`). 2. A project is linked (`archagent init`). ### Run in the CLI ```bash archagent auth login you@company.com archagent init agent_id=$(archagent --json create agent -n "Support Agent" -k support-agent \ -i "You help users solve billing and support problems clearly." | jq -r '.id') session_id=$(archagent --json create agentsession --agent "$agent_id" \ --instructions "Answer support questions clearly, ask one clarifying question if needed, and summarize the next action." | jq -r '.id') archagent exec agentsession "$session_id" \ -m "A customer says their invoice failed and wants to know what to try next." archagent describe agentsession "$session_id" --follow user_id=$(archagent --json create user --system-user -n "Support Test User" | jq -r '.id') thread_id=$(archagent --json create thread -t "Support test thread" \ --owner-type agent --owner-id "$agent_id" --skip-welcome-message | jq -r '.id') archagent create threadmember --thread "$thread_id" --user "$user_id" archagent create threadmessage --thread "$thread_id" --user "$user_id" \ -c "Can you help me figure out why my invoice keeps failing?" --wait routine_id=$(archagent --json create agentroutine --agent "$agent_id" \ -n "billing-triage" \ -e thread.message_added \ -t script \ --script "{ handled: true }" | jq -r '.id') archagent activate agentroutine "$routine_id" ``` Here `-k support-agent` gives the agent a stable lookup key you can search for and reuse later. `--system-user` creates a bot-style non-login user for testing or automation. Give these identities clear names so they're easy to spot in thread history and audit logs. They aren't a substitute for the approvals or human checks your deployment requires. If you need that identity to call APIs directly later, create a dedicated system-user token for it and treat that token like any other service credential: name it, track it, and revoke it when the workflow is done. ### What to check - the session replies like an agent, not just a saved object - the thread now has a test conversation in it - the routine is active and ready to react to future thread events ### What this confirms - agents keep their own identity over time - sessions are the quickest way to prove the agent can think and respond - threads and messages are where that behavior shows up in the product - routines are the bridge from one-off testing to ongoing behavior --- ## Sample 2: Move the setup into reviewable config ### What you are building The same agent setup, but moved into project config so the team can review, sync, and redeploy it instead of recreating it by hand. This is where you move from exploration to something the team can keep in source control. ### Prerequisites Use the same project from Sample 1. ### Run in the CLI ```bash archagent init --enable-configs archagent list configkinds archagent describe configsamples agent archagent sync configs archagent deploy configs ``` ### What to check - a local `configs/` directory in the project - a pulled-down view of the config objects the project knows about - a clean `configs deploy` path for reviewable changes When you edit an AgentTemplate sample, keep an explicit `model:` field. Use `openrouter/anthropic/claude-sonnet-latest` as the default starting point unless the sample has a specific provider requirement. ### What this confirms - the CLI is not just for one-off object creation - ArchAgents has a config layer for repeatable setup - once a pattern works, move it out of ad hoc commands and into tracked config Good next links: - [CLI](/docs/start-here/cli) - [Agents](/docs/build-agents/agents) - [Workflows](/docs/build-agents/workflows) - [Configs](/docs/build-agents/configs) --- ## Sample 3: Run a scheduled workflow with a script in the middle ### What you are building A project-wide job that runs on a schedule, calls a workflow, and uses a script node for the company-specific logic in the middle. This is the right pattern when the work belongs to the project, not to one named agent. ### Prerequisites Create a workflow config (use `archagent describe configsamples workflow` as a starting point) with a script node for the custom logic. Deploy it with `archagent deploy configs` and note the workflow config ID. The three pieces: - **workflow** = the visible process - **script** = the custom logic inside that process - **automation** = the schedule or trigger that starts it ### Run in the CLI ```bash automation_id=$(archagent --json create automation \ -n "Daily support summary" \ -t scheduled \ --schedule "0 9 * * 1-5" \ --config-id | jq -r '.id') archagent activate automation "$automation_id" archagent list automations archagent describe automation "$automation_id" archagent list automationruns --automation "$automation_id" ``` ### What to check - one named automation attached to your workflow config - an active project-wide job in the automation list - run history you can inspect after the schedule fires ### What this confirms - routines are for one agent's behavior - automations are for project-wide jobs - workflows and scripts become more useful when something repeatable starts them Good next links: - [Automations](/docs/build-agents/automations) - [Workflows](/docs/build-agents/workflows) - [Scripts](/docs/build-agents/scripts) --- ## Sample 4: Test a notification flow in a sandbox ### What you are building A notification or email flow you can trigger safely without touching production users or production mail. This is the right place to test the parts of your workspace that need production-like behavior before they touch production. ### Prerequisites Deploy a workflow or automation that sends a notification. The sandbox will capture emails instead of delivering them, so you can test the full flow safely. ### Run in the CLI ```bash sandbox_id=$(archagent --json create sandbox -n "Notification Test" -s notification-test | jq -r '.id') archagent activate sandbox archagent list sandboxes archagent describe sandbox "$sandbox_id" user_id=$(archagent --json create user --system-user -n "Sandbox Notification User" | jq -r '.id') thread_id=$(archagent --json create thread -t "Sandbox notification test" \ --user "$user_id" --skip-welcome-message | jq -r '.id') archagent create threadmember --thread "$thread_id" --user "$user_id" archagent create threadmessage --thread "$thread_id" --user "$user_id" \ -c "Trigger the sandbox notification path." --wait archagent list sandboxmails --sandbox "$sandbox_id" ``` ### What to check - the CLI is operating in the sandbox context after `archagent activate sandbox` - the thread and message exist inside the test boundary - captured email appears in `sandboxmails` instead of touching production ### What this confirms - sandboxes are not a toy environment; they are where realistic testing becomes believable - the same CLI loop still works, but the boundary changes - notification flows are much easier to trust once you can inspect captured output safely Good next links: - [Sandboxes](/docs/operate-agents/sandboxes) - [Portal](/docs/operate-agents/portal) --- ## Sample 5: Coordinate a rollout across two companies ### What you are building A shared rollout room between two companies: each side keeps its own private agents, users, and knowledge, but both sides collaborate through one network and one shared thread. This is the Network story in practical form. > Multi-company deployments start with two company spaces already set up in ArchAgents. The steps here begin once those company boundaries exist and the shared rollout work is ready to start. > If you want to enable this setup, work with the ArchAstro team first at hi@archastro.ai. ### Prerequisites 1. Both company spaces are provisioned (contact hi@archastro.ai for multi-company setup). 2. A network and shared thread exist for the rollout. 3. Each side has decided which agents and people participate. Each company keeps its private space. The network and thread are the only crossing point. ### Run in the CLI ```bash archagent list teams archagent describe team archagent list threads archagent describe thread archagent list threadmembers --thread operator_id=$(archagent --json create user --system-user -n "Rollout Operator" | jq -r '.id') archagent create threadmember --thread --user "$operator_id" archagent create threadmessage --thread --user "$operator_id" \ -c "Company A completed staging validation. Company B can start the rollout window review." --wait archagent list threadmessages --thread --full ``` ### What to check - one network and one shared thread you can inspect directly - one shared conversation that both companies can use without flattening everything into one tenant - visible participants and message history in the shared layer ### What this confirms - Network is not abstract architecture; it becomes a concrete collaboration room - the collaboration surface is intentionally small - CLI still matters in cross-company work because it lets you inspect, join, and operate the shared thread directly Good next links: - [Network](/docs/collaborate/agent-network) - [Network Getting Started](/docs/collaborate/agent-network-getting-started) - [Organizations](/docs/collaborate/organizations) --- ## Sample 6: Debug a cross-company integration by embedding the support agent ### What you are building A realistic debugging loop where an engineer explicitly approved by Company A to work in its support workspace uses a shared rollout thread plus Company A's support agent to diagnose a broken `acme-billing-webhooks` integration. This is the kind of flow that makes ArchAgents feel different: - the companies stay separate - the rollout thread is shared - the support agent keeps its own private tools, skills, and knowledge - the developer can still debug from the same attached surface the live agent uses ### Prerequisites 1. A shared rollout team and thread exist (from Sample 5). 2. Company A's support agent is a participant in the shared thread. 3. Company A has granted operator access to their ArchAgents workspace for this rollout. 4. Troubleshooting knowledge is connected to the support agent. 5. The relevant skill and tool are linked to the agent. ### Run from the CLI and coding agent ```bash archagent describe thread archagent list threadmembers --thread archagent list knowledgesources archagent list knowledgeingestions --status failed ``` Invoke embed inside the coding agent you are using for the rollout: ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` After you have search results, post the rollout note back to the shared thread: ```bash archagent create threadmessage --thread --user \ -c "Search results point to webhook retry validation as the likely blocker. Please confirm the retry path before the rollout window." --wait ``` ### What to check - the shared thread clearly shows who is collaborating - the embed session reflects the support agent's attached skills and tools - the search result comes from Company A's approved troubleshooting corpus - the thread gets a concrete next step instead of vague back-and-forth ### What this confirms - Network is not just shared chat; it supports debugging work across company lines - embed connects the live agent's surface to the local debugging loop, after the owning company authorizes it - knowledge, tools, and cross-company collaboration all meet in one operational flow Good next links: - [Embed](/docs/operate-agents/embed) - [Knowledge](/docs/build-agents/knowledge) - [Tools](/docs/build-agents/tools) - [Network](/docs/collaborate/agent-network) --- ## Sample 7: Deploy a real agent from a template ### What you are building A production-ready agent deployed from a single YAML file. This is the recommended workflow once you understand the basic model from Samples 1-2. One file defines everything: identity, tools, routines, and installations. One command deploys it. One test proves it works. ### Write the agent template Create `configs/agents/security-reviewer.yaml`: ```yaml kind: AgentTemplate agent_key: security-reviewer name: Security Reviewer model: openrouter/anthropic/claude-sonnet-latest identity: | You are a security code reviewer for our engineering team. When asked to review code, check for: - hardcoded secrets or credentials - SQL injection or command injection risks - missing input validation - overly permissive access controls Be specific about file paths and line numbers. Suggest fixes, not just problems. tools: - tool_type: builtin builtin_tool_key: search status: active - tool_type: builtin builtin_tool_key: knowledge_search status: active - tool_type: builtin builtin_tool_key: integrations status: active routines: - name: Respond in conversations description: Join threads and respond to messages handler_type: preset preset_name: participate event_type: thread.session.join event_config: thread.session.join: filters: {} status: active - name: Memory extraction (opt-in) description: Extracts and stores key facts after conversations when this routine is enabled handler_type: preset preset_name: auto_memory_capture event_type: thread.session.leave event_config: thread.session.leave: subject_is_agent: true status: active installations: - install_type: memory/long-term config: {} - install_type: archastro/thread config: {} ``` ### Validate and deploy ```bash archagent validate configs --kind AgentTemplate --file configs/agents/security-reviewer.yaml archagent deploy agent configs/agents/security-reviewer.yaml --name "Security Reviewer" ``` One command creates the agent with all tools, routines, and installations provisioned. ### Test it ```bash # Quick direct test session_id=$(archagent --json create agentsession --agent \ --instructions "Review code for security issues." | jq -r '.id') archagent exec agentsession "$session_id" \ -m "Review this function: def login(user, password): query = f'SELECT * FROM users WHERE name={user}'" ``` ### Test in a real conversation ```bash thread_id=$(archagent --json create thread -t "Security review" \ --owner-type agent --owner-id --skip-welcome-message | jq -r '.id') user_id=$(archagent --json create user --system-user -n "Engineer" | jq -r '.id') archagent create threadmember --thread "$thread_id" --user "$user_id" archagent create threadmessage --thread "$thread_id" --user "$user_id" \ -c "Can you review our auth module for SQL injection risks?" --wait ``` ### Test in a sandbox first For production agents, deploy to a sandbox before going live: ```bash # Switch to sandbox, deploy, and test archagent activate sandbox staging archagent deploy agent configs/agents/security-reviewer.yaml --name "Security Reviewer" # test in sandbox... # When ready, switch back to production and deploy archagent activate sandbox # (select production from the interactive prompt, or deactivate the sandbox) archagent deploy agent configs/agents/security-reviewer.yaml --name "Security Reviewer" ``` ### What to check - Agent responds with specific, actionable security feedback - Agent cites file paths and line numbers when reviewing code - Memory extraction routine (opt-in) stores key facts between conversations when enabled - The same YAML file deploys identically to sandbox and production --- ### AstroDev URL: https://latest.docs.archagents.com/docs/start-here/astrodev Summary: A local coding agent for interactive or headless work — run standalone or embed a live ArchAgents agent with its identity, tools, and skills. ## Overview AstroDev is the coding agent that ships with the ArchAgents CLI. You run it in a terminal, in the repo you're working on. It reads and edits local files, runs shell commands, and can open pull requests — the same loop you get from Claude Code, Codex, or Cursor, but as a single `archagent` command. Two things make it fit ArchAgents: 1. **It can embed a live agent.** Pick an agent from your linked workspace. AstroDev loads that agent's identity, default model, linked skills, and platform tools into the local coding loop, while keeping its file, shell, git, review, and delegation tools. 2. **It can run without an agent.** Leave the agent unset and you still get a full local coding session against the working directory, using the models and permissions you configure. Use AstroDev when you want a dedicated terminal session for coding work, when you want to debug or extend a platform agent against real files, or when you need a headless one-shot prompt in CI. It is **not** a replacement for the CLI verbs that create, deploy, and inspect platform objects. Use `archagent list`, `deploy`, and friends for that. AstroDev is the coding loop; the CLI is the operator surface. See [CLI](/docs/start-here/cli) and [Use ArchAgents from your coding agent](/docs/start-here/coding-agents). ### Key features | Feature | What it gives you | |---------|-------------------| | **Embedded agents** | Work as one live platform agent with its identity, default model, linked skills, and scoped platform tools | | **Local coding loop** | Read, search, edit, run shell and git commands, inspect diffs, review changes, and prepare pull requests | | **Reviewable autonomy** | Permission modes, a read-only plan mode, tool cards, and explicit plan approval | | **Resumable sessions** | Continue local conversation and tool history from `~/.astrodev` | | **Parallel work** | Delegate to subagents, isolate work in worktrees, and monitor background commands | | **Dynamic workflows** | Let the model generate a bounded JavaScript program that coordinates independent or staged agents | | **Model choice** | Use platform-routed models or configured OpenAI and xAI providers | | **Headless mode** | Run the same agent loop non-interactively with `-p` / `--print` for scripts and CI | --- ## Prerequisites 1. Install the CLI and sign in (see [Getting Started](/docs/start-here/getting-started)). 2. Connect the current directory if you want agent selection and project context: ```bash cd my-project archagent init archagent auth status ``` Running AstroDev always requires a platform CLI login, including standalone sessions and sessions that use a bring-your-own model. Provider login only supplies model credentials; it does not replace platform authentication. See [Models and providers](#models-and-providers). --- ## Run with an embedded agent Selecting an agent embeds that live platform agent in the AstroDev session. AstroDev wires the agent in automatically; you do not need to run `embed start`, `embed sync`, or `embed stop`. | Agent resource | How AstroDev uses it | |----------------|----------------------| | **Identity** | Adds the agent's persona and identity instructions to the coding session | | **Default model** | Uses the agent's configured model unless you choose another model or pass `--model` | | **Platform tools** | Lets the agent discover its deployed tools and call them through a permission-gated tool facade, under your existing platform access | | **Linked skills** | Lists the agent's skills and loads their instructions and supporting files only when needed | | **Local tools** | Keeps AstroDev's local file, shell, git, review, plan, and delegation capabilities; the embedded identity does not replace them | In the interactive TUI, linked skills also appear as `/skill:` commands. Choose **None** to run standalone; AstroDev then omits the platform agent's identity, tools, and skills but keeps the complete local coding surface. An embedded-agent AstroDev session is still a local AstroDev coding session. It does not attach to an existing platform thread or run the agent's routines, and its resumable conversation history stays under `~/.astrodev`. For persistent impersonation inside Claude Code, Codex, or Cursor, use [Embed](/docs/operate-agents/embed) instead. --- ## Start a session From any directory: ```bash archagent astrodev ``` That opens AstroDev's full-screen, alternate-screen TUI. On first paint you see the brand header, then session metadata (agent, session id, branch, working directory). After your first message the header collapses to a compact status bar so the transcript has room. Use Page Up, Page Down, or the mouse wheel to move through the session; AstroDev restores your normal shell screen when you exit. For scripts, pipes, and other non-interactive use, run headless mode with `--print` (or `-p`) instead of launching the TUI. ### Seed an agent Pass an agent id, lookup key, or name fragment so the selector starts focused: ```bash archagent astrodev support-agent archagent astrodev --agent agi_… ``` Inside a session you can switch agents with `/agent` (optional query to filter the list). ### Resume a previous session When you exit, the CLI prints the session id and a resume command: ```bash archagent astrodev --resume ``` From inside AstroDev, `/resume` picks a saved session or takes a matching id. Sessions and user-scope configuration live under `~/.astrodev` on your machine. ### Headless mode For scripts and CI, pass a prompt with `-p` or `--print`. That flag is the headless-mode switch; there is no separate `--headless` flag. ```bash archagent astrodev -p "Summarize the uncommitted diff" archagent astrodev -p "List failing tests" --output-format json --max-turns 8 archagent astrodev -p "Investigate this support issue" \ --agent support-agent --model --output-format json archagent astrodev -p "Continue the investigation" --resume ``` Headless runs require an existing CLI login and never open an interactive login flow. Use `--agent` with an exact agent id or lookup key; display names and fuzzy matches are not accepted, and the interactive positional agent argument is ignored. Without `--agent`, a fresh run is standalone with no platform agent attached. `--resume` continues the saved session with its original agent and history. Text output is the default and prints only the final assistant response. `--output-format json` prints an envelope with `type`, `subtype`, `is_error`, `session_id`, and `result`; failed runs exit nonzero. `--max-turns` bounds the agent loop. Headless embedded-agent runs use the selected agent's identity and linked skills, and they can discover its platform tools. There is no interactive approval panel: local tools run non-interactively, but deployed platform tools cannot execute in headless mode because every platform tool call fails closed. The commit and push guard remains active. --- ## The session chrome | Region | What it shows | |--------|----------------| | **Header** | Agent, full session id, git branch, working directory (compact after the first user message) | | **Transcript** | Messages, tool cards, plan panel, and status rows | | **Prompt** | Where you type; slash commands start with `/` | | **Footer** | Active model (`provider · model`), permission mode chip, key hints | ### Keyboard | Key | Action | |-----|--------| | `Enter` | Send (or queue while a turn is running) | | `Shift+Enter` / `Option+Enter` | Newline in the prompt | | `Shift+Tab` | Cycle permission mode (includes plan) | | `Esc` | Stop the in-flight turn — does **not** exit | | `Ctrl+C` | Quit the session | While a turn is running the footer switches to phase + queue hints (`tab` cycles delivery for the next message). --- ## Permission modes Permission mode is the baseline for how aggressively AstroDev acts without asking. Cycle with `Shift+Tab`, or set explicitly: ```text /mode /mode default /mode acceptEdits /mode plan /mode deny /mode auto /mode bypass ``` | Mode | Behavior | |------|----------| | **default** | Ask before unmatched tool use | | **acceptEdits** (`edits`) | Auto-allow file edits and writes; still ask for other tools | | **plan** | Read-only planning: reads allowed, file edits and writes denied until you approve a plan | | **deny** | Deny unmatched tool use by default | | **auto** | High autonomy — auto-approve actions (configured deny rules still apply); shown with a ⚠ chip | | **bypass** | High autonomy — skip the permission engine entirely; ⚠ chip | Fresh sessions default to **auto** when that mode is allowed. High-autonomy modes are impossible to miss in the footer. Your last mode is remembered across sessions when it is still allowed. --- ## Plan mode Plan mode is for "think first, change second." Enter it with `Shift+Tab` until the chip shows plan, or: ```text /plan /plan on /mode plan ``` While plan mode is on: - The session is read-only for file edits and writes. - The agent explores the codebase and builds a plan (markdown body + ordered steps). - A plan panel shows the full draft as it evolves — nothing is truncated for review. When a plan is ready, the review prompt lets you approve and execute the whole plan, approve only the next pending step, request changes with notes, or close the review pane. Approving the whole plan leaves plan mode and restores the permission mode you had before planning; requesting changes keeps the session in plan mode. You can also drive review from the `/plan` command: ```text /plan approve # accept the pending plan and execute it /plan step # approve and run only the next pending step /plan reject [notes] # stay in plan mode and revise /plan close # close the review pane without approving /plan help # show plan-mode usage ``` The agent can enter plan mode itself via its `plan` tool when it needs a read-only design pass. Either way, you review the markdown before edits land. Turn plan mode off when you want a normal coding loop again: ```text /plan off ``` --- ## Models and providers The footer shows the active route as `provider · model`. Platform-routed models appear as **astrodev · …** so the product name is what you see day to day. Bring-your-own providers keep their own ids (`openai · …`, `xai · …`). ### Inside the session ```text /model # pick or filter models /provider # switch platform | openai | xai /provider platform ``` ### Outside the session (CLI) Manage BYO credentials without changing your default model: ```bash archagent astrodev provider list archagent astrodev provider status archagent astrodev provider login openai archagent astrodev provider login xai --api-key sk-… archagent astrodev provider login openai --device-code # SSH / headless OAuth ``` `provider login` stores credentials only. Select the model afterward with `/model openai/…` or `/model xai/…` in the TUI (or `--model` for headless). --- ## Slash commands (essentials) Type `/` at the prompt for autocomplete. `/help` lists everything registered in the current session (built-ins plus skills). | Command | Purpose | |---------|---------| | `/help` | List slash commands | | `/agent [query]` | Switch platform agent | | `/model [query]` | Select model | | `/provider [platform\|openai\|xai]` | Select model provider | | `/mode […]` | Show or set permission mode | | `/plan [on\|off\|approve\|step\|reject\|close\|help]` | Plan mode and plan review | | `/new` | Fresh session with the current agent | | `/resume [id]` | Resume a saved session | | `/clear` | Reset conversation/model context in the same session while keeping the selected agent and project instructions | | `/theme [light\|dark\|auto\|toggle]` | Color theme | | `/quit` | Exit | ### Code review and shipping | Command | Purpose | |---------|---------| | `/diff` | Summary of uncommitted changes | | `/review` | Read-only review of local changes | | `/code-review` | Severity-ranked findings with file:line | | `/security-review` | Auth, secrets, injection-focused review | | `/simplify` | Flag over-engineering and dead code | | `/pr-context` | Branch, files, PR metadata, CI | | `/pr-describe` | Generate PR body (summary, risk, impact, testing) | | `/pr-create [--submit]` | Preview a PR; `--submit` opens it | | `/pr-review ` | Review a remote PR | | `/ci` | CI status and actionable failures | ### Parallel work | Command | Purpose | |---------|---------| | `/worktree ` | Isolated branch + worktree for a task | | `/worktrees` | Status of worktrees | | `/worktree-agent …` | Write-capable subagent in a worktree | | `/delegate [--bg] ` | Hand off work to a subagent | | `/subagents` / `/jobs` | Compatibility views for subagents and shell jobs | | `/work [action] [id]` | List, inspect, stop, pause, resume, or rerun background work | | `/monitor ` | Background process whose output becomes events | Skills attached to the selected platform agent appear as `/skill:…` (and related skill management under `/skills`). ### Unified background-work control `/work` is the common control surface for workflows (`wf-*`), subagents (`sa-*`), shell jobs (`bg_*`), monitors (`mon-*`), and long-running goals or loops (`gl_*`, `rl_*`, `lp_*`). Every runtime plugs into the same work-provider contract for listing, status, output, control, and session cleanup. The list shows each item's safe controls; unsupported actions fail explicitly instead of pretending that unlike runtimes have identical suspension semantics. ```text /work # list every background item and its controls /work status # state, parent, phase, and available controls /work output # captured output or terminal summary /work stop # cancel one item or all live work /work pause # pause at that runtime's safe boundary /work resume # continue a paused item /work rerun # start a new run when the item supports it ``` Pause is capability-safe: shell jobs and monitors use operating-system process suspension where supported, workflows let already-running agents finish and hold new agent dispatches, and goal/ralph/loop jobs stop chaining after the current turn. Stopping a long-running goal or loop also prevents another turn but does not pretend it can rewind a model call already in flight. A one-shot subagent cannot be safely suspended mid-model-call, so it supports status, output, and stop but not pause/resume. Status uses the same normalized states across providers (`running`, `paused`, `waiting`, `blocked`, `succeeded`, `failed`, or `stopped`) and includes a runtime's more specific native status when useful. The model has the same split surface through read-only `work_status` and permission-gated `work_control` tools. The inventory is unified, but persistence remains capability-specific. Shell jobs, monitors, subagents, and workflow processes are stopped and drained when a session is cleared, replaced, resumed away from, or exited; they are not checkpointed. Long-running goal/ralph/loop metadata is deleted by `/clear`, remains attached to the old session across `/new` or `/resume`, and can be restored when that session is resumed. Exiting disposes its in-memory timer without deleting the saved metadata. `output` appears only for work kinds that retain output or a terminal summary. Long-running goals and loops expose their objective and latest lifecycle update through `status` instead of claiming a separate output stream. --- ## Dynamic workflows AstroDev can decide to use its model-callable `workflow` tool when a task benefits from many independent agents or a repeatable sequence of agent stages. You can also ask directly: “Use a workflow to investigate these services in parallel.” This is a tool the model calls during a turn, not a slash command you invoke yourself. The model supplies a self-contained JavaScript program. Every program begins with literal metadata and returns a JSON-serializable result: ```js export const meta = { name: "review-services", description: "Review several services and combine the findings", phases: [ { title: "Review", detail: "Inspect each service in parallel" }, { title: "Summarize" }, ], }; phase("Review"); const findings = await parallel([ () => agent("Review the API service", { label: "api", phase: "Review" }), () => agent("Review the web service", { label: "web", phase: "Review" }), ]); phase("Summarize"); return agent( `Combine these findings into one prioritized report: ${JSON.stringify(findings)}`, { label: "summary", phase: "Summarize" }, ); ``` The generated program has a small orchestration API: | Global | Purpose | |--------|---------| | `args` | The JSON value passed to the workflow | | `agent(prompt, options)` | Run an isolated AstroDev agent and return its result | | `parallel([() => …])` | Start independent tasks together and preserve their result order | | `pipeline(items, ...stages)` | Run each item through a sequence of stages; items run concurrently | | `phase(title)` | Report a phase declared in `meta.phases` | | `log(value)` | Add a bounded diagnostic entry to the saved run | `agent` accepts `label`, `phase`, `model`, and `schema`. The `schema` option requests structured JSON from that agent. Claude Code-specific options such as `isolation`, `agentType`, and `effort` are not supported and fail explicitly instead of being ignored. Phase declarations must use objects such as `{ title: "Review", detail: "optional" }`, not bare strings. ### Background runs and results In an interactive tracked session, a workflow runs in the background by default so the main conversation remains usable. AstroDev immediately returns a `wf-*` work id, exposes its phase and child agents through `/work`, and injects a typed work-completion event when the workflow settles. `/work pause` cooperatively holds new agent dispatches while already-running agents finish; `/work resume` releases them. The model can request a foreground run when the current turn must consume its result. Exiting, clearing, replacing, or resuming away from the session stops and drains tracked workflow work rather than leaving child processes behind. The workflow card shows the generated JavaScript with line numbers. Expand it to inspect the complete script; successful foreground runs show status and timing without replacing the source with a deeply expanded result tree. Inline scripts and JSON run snapshots are saved inside the session's `workflows` directory under `~/.astrodev`. `/work status ` reports the saved script path. Edit that file with the normal file tools, then `/work rerun ` starts a fresh execution from its current contents; rerun does not resume a JavaScript continuation. Workflow processes are not restored after AstroDev exits. ### Execution boundary Generated JavaScript does not run inside the AstroDev process. AstroDev parses it first, rejects imports and dangerous runtime identifiers, then starts a memory-limited Node child process with filesystem and network permissions disabled. The child receives only the workflow API above. Agent requests cross a bounded JSON-lines IPC bridge back to the AstroDev harness, where the normal permission, read-only, model, and commit guards still apply. Workflow runs are bounded by time, script size, retained logs, IPC message size, concurrency, and agent count. They cannot use `process`, `require`, dynamic imports, `fetch`, filesystem APIs, environment variables, nested workflows, runtime code generation, or nondeterministic `Math.random()`. --- ## How AstroDev relates to other surfaces | Surface | Role | |---------|------| | **AstroDev** | Interactive or headless local coding agent; can embed a platform agent's identity, tools, and skills for the session | | **CLI verbs** (`list`, `deploy`, `create`, …) | Create and operate platform objects; source of truth for automation | | **Astrorun** | Local processing and review queue that can use AstroDev as a headless processor — see [Astrorun](/docs/start-here/astrorun) | | **Coding-agent plugins** (Claude Code, Codex, Cursor) | Same platform operations from the chat where you already work — see [coding agents](/docs/start-here/coding-agents) | | **Embed** | Step into one live agent's exact tools and skills *inside* Claude Code / Codex / Cursor — see [Embed](/docs/operate-agents/embed) | | **ArchAgents Portal** | Review agents, threads, activity, and org settings in the browser — see [Portal](/docs/operate-agents/portal) | Pick the surface that matches the job: AstroDev for a focused local coding session, persistent Embed when an existing coding agent should *be* a specific live agent for a while, and CLI verbs for scripted deploys and inspection. --- ## Typical workflows ### Local feature work ```bash cd my-repo archagent astrodev ``` Describe the change. Use `/mode acceptEdits` or stay in auto if you trust the loop. When the diff looks right: `/review`, then `/pr-describe` and `/pr-create --submit`. ### Plan before touching the tree ```text /plan on ``` Ask for an approach on a risky migration or multi-service change. Read the full plan panel. Approve when the steps match what you want; reject and refine if not. ### Debug as a platform agent ```bash archagent astrodev support-agent ``` The session inherits that agent's identity, default model, linked skills, and scoped platform-tool surface while retaining AstroDev's local coding tools. Reproduce a customer-facing failure against local config files, or draft a template change while staying in the agent's voice. ### Scripted check in CI ```bash archagent auth status # non-interactive token already configured archagent astrodev --print "Report whether the PR description matches the diff" \ --output-format json --max-turns 6 ``` --- ## Where to go next 1. [CLI](/docs/start-here/cli) — install, auth, init, and day-to-day operator commands. 2. [Astrorun](/docs/start-here/astrorun) — turn agent work into a local processing queue with persisted review records. 3. [Use ArchAgents from your coding agent](/docs/start-here/coding-agents) — Claude Code, Codex, and Cursor plugin setup. 4. [Embed](/docs/operate-agents/embed) — run as a live agent inside those coding agents. 5. [Agents](/docs/build-agents/agents) — identity, tools, routines, and the model behind every agent you can select in AstroDev. 6. [Skills](/docs/build-agents/skills) — reusable packages that show up as slash commands when attached to an agent. --- ### Astrorun URL: https://latest.docs.archagents.com/docs/start-here/astrorun Summary: A local work queue that finds agent work, drafts responses through your preferred coding harness, and keeps review and completion records on your machine. ## Overview Astrorun turns agent work into a local review queue. Run it from a linked project and it watches for new human activity in accessible agent threads, sends each item to a coding harness, and shows the resulting draft before anything is posted. You can also create one-off manual tasks from the dashboard. Astrorun is an orchestrator, not another model provider. It can run work through AstroDev, Claude Code, Codex, or Rovo Dev using the tools and credentials already available on your machine. AstroDev is always available with the ArchAgents CLI; the other harnesses are optional. Review is required by default. In that mode, Astrorun never posts a generated thread reply until you approve it. Rejecting a reply can resume the same harness conversation with correction notes, and Astrorun preserves the earlier drafts so you can compare them with the replacement. ### See Astrorun in action The dashboard keeps discovery, execution, and review in one place. The work queue groups candidates, drafts awaiting review, running or live sessions, queued work, and completed outcomes. Selecting an item opens its source context, draft, proposed action, transcript, and available controls. [Diagram: Astrorun dashboard showing candidate, review, running live, queued, and completed work beside a drafted customer reply] Review is conversational rather than destructive. Press `x` on a draft to send specific feedback back into the same harness session. Astrorun preserves the earlier attempt and returns the replacement to the review queue. [Diagram: Astrorun review dashboard with a correction prompt asking the harness to lead with customer impact] Settings let you choose the local processor, switch between headless and live execution, and decide whether candidates and drafts require approval. Live mode is available for supported processors when `tmux` is installed. [Diagram: Astrorun settings showing available processors, headless and live modes, and the review-required toggle] ### Key features | Feature | What it gives you | |---------|-------------------| | **Thread work discovery** | Finds new human activity in threads where you can act through an accessible agent | | **Manual tasks** | Adds local one-off work directly from the dashboard | | **Multiple processors** | Runs work through AstroDev, Claude Code, Codex, or Rovo Dev | | **Review-first actions** | Holds drafted replies for approval, correction, or rejection before applying them | | **Draft history** | Keeps rejected agent replies so reviewers can expand and compare earlier attempts | | **Live sessions** | Opens supported processors in tmux for interactive steering, then returns the updated draft to review | | **Durable review state** | Restores manual tasks, saved drafts, completed work, and live-session records after a restart | | **Local audit trail** | Keeps item state, outcomes, logs, and transcript references on your machine | --- ## Prerequisites 1. Install the CLI and sign in (see [Getting Started](/docs/start-here/getting-started)). 2. Link the current directory to the app whose agent threads you want Astrorun to watch: ```bash cd my-project archagent init archagent auth status ``` 3. If you plan to use Claude Code, Codex, or Rovo Dev, install that CLI and confirm it can run from the same shell. Provider authentication, plan limits, and credits are managed by that harness. 4. Install `tmux` if you want live sessions. Headless work does not require it. Thread work also needs an accessible agent in the conversation. Astrorun selects an agent you own or can use; it does not reply as another organization's private agent. --- ## Start Astrorun From a linked project: ```bash archagent astrorun ``` On the first launch, Astrorun probes the supported harnesses and tmux, then asks you to choose a default processor. The dashboard opens with the work queue on the left and details for the selected item on the right. Astrorun runs in the foreground. Quitting stops discovery and headless processing, but it does not discard stored items. A detached live tmux session can continue without the dashboard, and Astrorun restores its record the next time you start it. ### What enters the queue Astrorun has three work sources: | Source | How it works | |--------|--------------| | **Thread activity** | Polls the linked app for recent, accessible threads whose latest message is from a human. With review required, new items first appear as candidates and wait for you to enqueue them. | | **Workflow work items** | Polls queued embed-agent handoffs from durable workflows (automation- or routine-backed). After review, Astrorun claims, starts, and submits the work item so the workflow can resume. | | **Manual task** | Press `n`, describe the task, choose a processor and mode, and press `Enter`. Astrorun stores the task before enqueueing it, so it survives a restart. | Thread discovery is incremental. Astrorun anchors new work after the selected agent's last reply, avoids replying to its own output, and deduplicates repeated observations of the same activity. On a cold start, it looks at recent activity rather than replaying an entire thread history. ### Queue sections | Section | Meaning | |---------|---------| | **Candidates** | Discovered thread or workflow work waiting for you to enqueue | | **Queued** | Accepted work waiting for an available processor slot | | **Running** | A harness is drafting, resuming, extracting, or applying the item | | **Review** | A draft or action is ready for a human decision | | **Done** | Completed or failed work with its outcome retained | The detail pane shows the source conversation or task, the current drafted response, the proposed action, prior drafts, outcome or error, and a transcript path when the processor provides one. --- ## Review and refine work With **Review required** on, the normal thread-reply flow is: 1. Select a candidate and press `Enter` to enqueue it. 2. Astrorun runs the selected processor and moves the draft to **Review**. 3. Read the conversation, draft, and proposed action. 4. Press `a` to approve and post the reply as the selected agent, or press `x` to correct or reject it. When you press `x`, Astrorun opens a correction prompt: - Enter feedback and press `Enter` to resume the same harness conversation. The processor receives your correction and produces a new draft. - Submit an empty correction to discard the draft without recomputing it. - Press `Esc` to cancel and leave the item unchanged. Earlier rejected replies remain attached to the item in order. Press `h` while viewing it to expand or collapse those replies above the current draft. This makes wording and factual changes visible without replacing the review record. For a manual task, approval marks the task complete; it does not perform a platform action. Failed items remain in **Done** and can be retried with `r`. Pressing `x` on a completed item archives it when that work source supports archiving. Archived items leave the dashboard, but their audit records remain in the completed store. ### Review-free operation You can turn **Review required** off in settings. New candidates then enqueue automatically, and completed drafts apply without waiting for approval. This setting removes the human checkpoint for platform actions. Use it only when you trust the selected agent, processor, instructions, and thread scope. A settings change applies on the next Astrorun launch, not to the controller already running. --- ## Headless and live modes | Mode | Behavior | Availability | |------|----------|--------------| | **Headless** | Runs the processor non-interactively and returns its structured draft to Astrorun | AstroDev, Claude Code, Codex, and Rovo Dev | | **Live** | Opens an interactive processor in a dedicated tmux session, then extracts the final draft when the processor exits | Claude Code and Codex; requires tmux | Live mode is useful when a draft needs investigation or hands-on steering. Select a review item and press `t` to attach or resume it interactively. The live harness continues the same conversation where possible, but it does not post the reply itself. When you exit or kill the harness process, Astrorun finalizes the session, extracts the updated result, and returns the item to the normal review flow. Detaching from tmux is different from exiting the harness: - **Detach** to leave the processor running. The item remains live and can be reattached. - **Exit or kill the harness process** to end live mode. Astrorun finalizes the work and removes the live indicator. - Press `e` in Astrorun to end the selected live session and request final extraction. You can list or attach to live sessions without opening the dashboard: ```bash archagent astrorun attach archagent astrorun attach ``` Astrorun uses a dedicated tmux socket, so these sessions do not mix with your normal tmux server. --- ## Dashboard keyboard reference ### Navigate | Key | Action | |-----|--------| | `Left` / `Right` | Focus the queue or detail pane | | `Up` / `Down` | Select queue items; scroll when the detail pane is focused | | `j` / `k` | Scroll the detail pane | | `Page Up` / `Page Down` | Scroll by a page | | `Ctrl+U` / `Ctrl+D` | Scroll by half a page | | `Ctrl+B` / `Ctrl+F` | Scroll by a page | | `g` / `G` | Jump to the top or bottom | | `h` | Expand or collapse previous agent replies | | Mouse drag | Copy selected text | Clicking a transcript path copies it to the clipboard. You can also drag the divider between the queue and detail panes to resize them. ### Act on work | Key | Action | |-----|--------| | `Enter` | Enqueue the selected candidate | | `a` | Approve the current review action | | `x` | Correct or reject a draft; archive supported completed work | | `r` | Retry a failed item | | `t` | Attach to or resume a live-capable item | | `e` | End the selected live session and finalize it | | `n` | Create a manual task | | `Shift+N` | Create an invoked automation run | ### Create a manual task | Key | Action | |-----|--------| | `Shift+Tab` | Cycle the processor for this task | | `Option+M` | Toggle headless/live for this task | | `Enter` | Create the task | | `Esc` | Cancel | `Option+M` only changes mode when the selected processor supports live work and tmux is available. If the footer says **mode unavailable**, choose Claude Code or Codex and confirm tmux was detected. ### Create an automation run Press `Shift+N`, choose **Automation** with the arrow keys, and press `Enter`. If manual tasks are also available, the chooser starts on **Manual task**. [Diagram: Astrorun new task chooser with Automation selected] The next screen lists `automation.invoked` workflows available in the linked app. A workflow can remain visible when it is paused or otherwise unavailable, so check the status shown beside its name before continuing. [Diagram: Astrorun automation picker with Customer escalation review selected and two other available automations] Choose an automation and press `Enter`. Astrorun builds the form from the automation's invoke contract, including required inputs, fixed installation values, thread references, and participant roles. [Diagram: Astrorun automation form showing customer account, severity, incident summary, source thread, and a locked operating channel] Participant fields open a searchable agent picker. Search by agent name, organization, lookup key, or ID, then press `Enter` to assign the role. [Diagram: Astrorun participant picker assigning the Support Triage agent to the Reporter role] Review the completed fields and press `Enter` on the last field to create the run. Astrorun shows the durable run ID and continues polling until the platform reports completion or failure. [Diagram: Astrorun automation form with reporter, resolver, and optional approver roles assigned and ready to run] [Diagram: Astrorun confirmation showing a completed customer escalation automation run and its durable run ID] ### Panels and application | Key | Action | |-----|--------| | `s` | Open settings | | `?` | Open key-binding help | | `q` / `Esc` | Close the active panel, or quit from the dashboard | | `Ctrl+C` | Quit | --- ## Settings Press `s` to configure Astrorun: | Setting | Purpose | |---------|---------| | **Processor** | Default harness for new work | | **Mode** | Default headless or live execution mode | | **Review required** | Hold candidates and drafts for human approval, or enqueue and apply automatically | | **Theme** | Terminal color theme | Use `Up` / `Down` and `Enter` to change a setting. Press `r` to probe installed harnesses and tmux again, or `t` to cycle the theme. Processor choices and probe results are cached so startup does not repeatedly invoke every CLI. Re-probe after installing a harness, fixing its executable path, or installing tmux. Mode and review-policy changes take effect on the next Astrorun launch. --- ## Durability and recovery Astrorun stores its state below the CLI's user configuration directory: ```text ~/.config/archagent/autorun/ ├── settings.json ├── logs/astrorun.log └── work-items/ └── done/ ``` The work-item store is the source of truth for persisted review and completion records. Those records preserve their source, processor, current response, earlier rejected responses, action metadata, outcome, and live-session information. Completed and archived records move into `done/` instead of disappearing from disk. On startup Astrorun reconciles durable records with live processes. If a response is already saved, it restores that item to review rather than silently drafting it again. If a live process ended while the dashboard was away, Astrorun finalizes or recovers the item from its recorded session state. Manual tasks, saved review drafts, completed history, and live-session records survive a restart. An ordinary thread item that was only queued or running headlessly is not yet durable; after a restart, polling may rediscover it as a candidate. Use the maintenance commands below only when you intentionally want to remove persisted state. --- ## Maintenance commands ### Clean up live sessions ```bash archagent astrorun --cleanup ``` This kills Astrorun's live tmux sessions and prunes their live-session records, then exits. It is useful after a crash or stale tmux state. It does not clear the full work queue or completed history. ### Clear the item store ```bash archagent astrorun clear ``` This is a destructive reset. Astrorun first ends live sessions, then clears active work items and completed history. It leaves CLI authentication and Astrorun settings in place. Use it when you want a completely empty dashboard, not as routine recovery for one failed item. --- ## Troubleshooting ### No thread work appears Check that: - `archagent auth status` succeeds and the current directory is linked to the intended app. - The thread includes an agent you own or can use. - The latest new activity is from a human; Astrorun does not create work in response to its own agent message. - The activity is recent or follows an earlier reply from the selected agent. A cold start does not replay unlimited historical activity. - With review required, you looked under **Candidates** and pressed `Enter` to enqueue the item. ### A processor is unavailable Run that harness directly to verify it is installed and authenticated, then open settings and press `r` to re-probe. You can always select AstroDev because it ships with the CLI. Authentication failures, exhausted credits, provider limits, and nonzero harness exits appear as failed work rather than platform login failures. Inspect the item's error and the Astrorun log. ### Live mode is unavailable Live mode requires both tmux and a live-capable processor. Install tmux, select Claude Code or Codex, then press `r` in settings. AstroDev and Rovo Dev currently run headlessly in Astrorun. ### An item still says it is live Detaching intentionally keeps the session live. Use `archagent astrorun attach` to inspect recorded sessions, reattach and exit the harness, press `e` from the dashboard, or use `archagent astrorun --cleanup` for stale live state. ### Astrorun appears stuck The selected harness may still be running, waiting on a provider, or finalizing a live transcript. Check the detail pane, then inspect: ```text ~/.config/archagent/autorun/logs/astrorun.log ``` The log records item ids, lifecycle transitions, processor selection, durable-store decisions, live-session reconciliation, and errors. Use the item id from the dashboard to follow one work item across those events. --- ## How Astrorun relates to other surfaces | Surface | Role | |---------|------| | **Astrorun** | Local discovery, processing, review, and application queue for agent work | | **AstroDev** | Interactive or headless local coding agent; one of Astrorun's available processors | | **Claude Code / Codex / Rovo Dev** | Optional local harnesses Astrorun can invoke with their existing credentials | | **Agent routines and automations** | Server-side scheduled or event-driven work that continues without your local terminal | | **CLI verbs** (`list`, `deploy`, `create`, …) | Create and operate platform objects directly | | **ArchAgents Portal** | Review agents, threads, activity, and organization settings in the browser | Use Astrorun when you want a local inbox of agent work with a durable review gate. Use [AstroDev](/docs/start-here/astrodev) for a focused coding conversation, and use [automations](/docs/build-agents/automations) or [workflows](/docs/build-agents/workflows) for server-side execution. --- ## Typical workflows ### Review agent thread replies ```bash cd my-project archagent astrorun ``` Select a candidate and press `Enter`. Review the draft, press `a` to post it, or press `x` and explain what should change. Use `h` to compare earlier rejected replies with the latest result. ### Run a one-off local task Press `n`, enter the work, use `Shift+Tab` to select a processor, and press `Enter`. Review the response and approve it to mark the task complete. ### Take a draft live Select a compatible item and press `t`. Investigate or refine it in Claude Code or Codex. Detach if it should keep running; exit the harness when you want Astrorun to extract the updated result and return it to review. ### Resume after a restart Start `archagent astrorun` again. Manual tasks, saved review items, and completed history reappear automatically; polling may rediscover interrupted headless thread work as a candidate. If a live tmux session is still running, press `t` on the item or use `archagent astrorun attach`. --- ## Where to go next 1. [CLI](/docs/start-here/cli) — installation, authentication, project linking, and day-to-day commands. 2. [AstroDev](/docs/start-here/astrodev) — understand the built-in coding harness Astrorun can use for headless work. 3. [Agents](/docs/build-agents/agents) — configure the identities Astrorun uses to reply in threads. 4. [Automations](/docs/build-agents/automations) — move suitable work from a local queue to server-side execution. 5. [Workflows](/docs/build-agents/workflows) — build multi-step, persistent agent processes. --- ## Notes for coding agents - Treat docs URLs as canonical. - The `archagent` CLI is the primary surface — prefer it over inventing new wrappers. - Use `archagent --help` to discover the exact flags for any command. - Ask for missing environment variables before destructive operations.