# ArchAstro Docs (Extended LLM Index) Use this index to discover canonical pages for product, API, and CLI usage. Prefer linked pages over inferred behavior. ## Documentation Pages ### API Reference URL: https://latest.docs.archastro.ai/docs/api-reference Summary: Human-readable reference for the public ArchAstro Platform API. Use the API reference for endpoint-level method, path, authentication, parameter, request body, and response examples. --- ### Getting Started URL: https://latest.docs.archastro.ai/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 [developers.archastro.ai](https://developers.archastro.ai) and create an account. [Diagram: Sign-in page asking for your work email] --- ## 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/archastro ``` ### Linux ```bash curl -fsSL https://archastro.ai/install.sh | bash ``` ### Windows ```powershell irm https://archastro.ai/install.ps1 | iex ``` Verify: ```bash archastro --help ``` ### Set up your coding tool ```bash archastro setup ``` Installs the ArchAstro 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 archastro auth login ``` The browser opens so you can authorize the local session. --- ## 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 archastro list agentsamples archastro install agentsample ``` ### Assistant Embed the Onboarding Agent in your coding tool and let it interview you, author the skills, and deploy them. ```bash archastro 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 `archastro 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 ArchAstro from your coding tool](/docs/start-here/coding-agents): how the embed plugin works in practice. 4. [ArchAgents](https://docs.archagents.com/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: archastro auth login ``` Fix: ```bash archastro auth login archastro auth status ``` ### 2. The embed command does nothing Restart your coding tool once after `archastro 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. --- ### Use ArchAstro from your coding agent URL: https://latest.docs.archastro.ai/docs/start-here/coding-agents Summary: Claude Code, Codex, and Cursor are the fastest, safest way to drive ArchAstro from your development workflow. ## Overview The fastest way to use ArchAstro is through the coding agent you already work in: Claude Code, Codex, or Cursor. One setup command installs a ArchAstro 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 ArchAstro 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 archastro setup ``` That one command installs the ArchAstro 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 ArchAstro 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 ArchAstro project linked. Use the ArchAstro 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 ArchAstro 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. --- ### Organizations URL: https://latest.docs.archastro.ai/docs/collaborate/organizations Summary: Your company's private space in ArchAstro, agents, teams, knowledge, and sign-in all scoped to your organization. ## Overview Your organization is your company's space in ArchAstro. 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 [ArchAgents](https://docs.archagents.com/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, ArchAstro 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 archastro list orgs archastro 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 [ArchAgents](https://docs.archagents.com/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 ArchAstro 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. [ArchAgents](https://docs.archagents.com/docs/collaborate/agent-network): collaborate across organizations. 3. [Sandboxes](/docs/operate-agents/sandboxes): test agents in isolation before production. --- ### Developer Portal URL: https://latest.docs.archastro.ai/docs/operate-agents/portal Summary: Review and manage what you've deployed: agents, networks, activity, and org settings. ## Overview Developer Portal at [https://developers.archastro.ai](https://developers.archastro.ai) 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 [ArchAgents](https://docs.archagents.com/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 [ArchAgents](https://docs.archagents.com/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 [ArchAgents](https://docs.archagents.com/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. --- ### Agent Memory URL: https://latest.docs.archastro.ai/docs/operate-agents/agent-memory Summary: Use memory to let an agent retain the right facts over time without turning it into an unreviewable black box. ## Overview Agent memory is how an ArchAstro 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 archastro list agentworkingmemory --agent archastro 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. Developer Portal mirrors the same view: open the agent in [Developer 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 (`archastro 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. --- ### Sandboxes URL: https://latest.docs.archastro.ai/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 Developer 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 archastro 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 Developer 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 archastro list sandboxmails --sandbox dsb_abc123 archastro describe sandboxmail sem_abc123 --sandbox dsb_abc123 ``` ### Cleaning up ```bash archastro delete sandboxmail sem_abc123 --sandbox dsb_abc123 archastro 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 archastro activate sandbox # List sandboxes, active sandbox is marked with * archastro 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 --- ## Developer Portal Developer Portal at `https://developers.archastro.ai` 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.archastro.ai/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 app 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: ArchAstro 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 app: 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 archastro 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 app. 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 Developer 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 archastro create agentroutine --agent \ -n "billing-triage" \ -e message.created \ -t script \ --script "{ route: \"billing\", priority: \"high\" }" archastro 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 conversations | Built-in conversation handler | | `preset: triage` | Agent mostly needs a local/embedded environment to do real work | Joins like `participate`, but acknowledges and tracks work on the thread task list instead of attempting it from the cloud | | `preset: send_message` | Agent should compose one message after an event or invocation | One-shot LLM session delivered to a target thread | | `preset: auto_memory_capture` | Extract and store key facts when a conversation ends (opt-in) | Built-in memory extraction | | `preset: do_task` | Agent should think and act on a schedule or event | Full LLM session with all agent tools | | `script` | Deterministic logic (routing, filtering, transformations) | ArchAstro script expression | | `workflow_graph` | Multi-step process with branching or approvals | Workflow config | The `do_task` preset gives the agent full LLM reasoning with access to all its configured tools. Use it for scheduled reports, periodic reviews, or any task that requires the agent to think. 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. --- ## 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 archastro create thread -t "Billing support" --owner-type agent --owner-id archastro create user --system-user -n "Demo User" archastro create threadmember --thread --user archastro 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 archastro 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: {} 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`, `message.created`, `schedule.cron`. - For cron routines, add `schedule: "0 9 * * 1"` (a cron expression) 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 archastro validate configs --kind AgentTemplate --file agent.yaml ``` Run this before `deploy` to catch schema errors early. --- ### Knowledge URL: https://latest.docs.archastro.ai/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 archastro list integrations archastro 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 archastro list contextsources archastro list contextsources --installation archastro describe contextsource ``` If you need to create or tune a source from the CLI: ```bash archastro create contextsource \ --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 contextsource` and `list contextsources` 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 archastro list contextingestions archastro list contextingestions --status failed archastro list contextingestions --source archastro describe contextingestion ``` 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 archastro list contextitems --source archastro describe contextitem ``` 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 archastro list contextcredentials archastro describe contextcredential ``` 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 ArchAgents 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 [ArchAgents](https://docs.archagents.com/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 [ArchAgents](https://docs.archagents.com/docs/collaborate/agent-network) for cross-company knowledge boundaries. --- ### Workflows URL: https://latest.docs.archastro.ai/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 archastro configs kinds archastro configs sample workflow --to-file ./tmp/workflow.sample.yaml archastro validate configs -k workflow -f ./tmp/workflow.sample.yaml ``` After you have a workflow shape you want to keep: ```bash archastro configs sync archastro configs deploy ``` This is the primary path for workflows. They belong in source control where your team can review and iterate on them. ### Portal editor Developer 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 ArchAstro 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 `archastro configs sample 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 both scripts and lightweight expressions: - **Scripts** for custom logic and multi-step data handling - **Expressions** for simple conditions and field access 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. ### Attaching a workflow to an agent routine Once the workflow exists as a config, a routine can point at it by config id: ```bash archastro 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. --- ## Where to go next 1. Use `archastro configs sample 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. --- ### Integrations URL: https://latest.docs.archastro.ai/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 ArchAstro. 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 app. Inspect the current server before automating setup: ```bash archastro list integrationproviders archastro 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 archastro list integrations --provider --auth-type app_installation --org archastro create agentinstallation \ --agent \ --kind enablement/ \ --shared-integration ``` Do not place a provider's external installation ID in the enablement configuration. `--shared-integration` expects the ArchAstro integration resource ID. ## Personal OAuth workflow Personal integrations belong to one agent and authorize through the person whose account the agent will use: ```bash archastro create agentinstallation \ --agent \ --kind integration/ archastro authorize agentinstallation archastro 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 archastro list agentinstallations --agent archastro 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.archastro.ai/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 ArchAstro 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 ArchAstro 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: - ArchAstro 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 the [developer portal](https://developers.archastro.ai) as an organization admin. 2. Select the target app and organization, then open **My Org → Integrations**. 3. On the Slack card, select **Enable**. 4. Choose the Slack workspace and approve the requested permissions. 5. Return to the portal and confirm that Slack shows **Connected**. ![Organization integrations page with Slack available to enable](/screenshots/settings-integrations.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 ArchAstro 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 archastro 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 ArchAstro integration: ```bash archastro list integrations \ --provider slack_bot \ --auth-type app_installation \ --org archastro create agentinstallation \ --agent \ --kind enablement/slack_bot \ --shared-integration ``` `` is the ArchAstro 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 ArchAstro 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 ArchAstro installation state. ### Step 5: verify the installation ```bash archastro list agentinstallations --agent archastro 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 archastro create agentinstallation \ --agent \ --kind integration/slack ``` Save the returned installation ID. ### Step 2: complete OAuth ```bash archastro 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 archastro activate agentinstallation archastro 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. The generic developer CLI does not currently expose the internal, no-network resident assignment as a first-class command. The runtime operation is `slack.channel_bindings.assign`, used by a deployed Slack management workflow. For a product-managed experience, deploy a slash-command or interactivity workflow that calls: ```javascript let bindings = import("slack.channel_bindings") unwrap(bindings.assign({ slack_team_id: input.slack_team_id, channel_id: input.channel_id, agent_user_id: input.agent_user_id })) ``` The operation creates a bare internal binding when needed and enforces private-channel membership and Slack Connect safety checks. Use `slack.channel_bindings.remove_agents` to clear the resident without deleting the binding. ### 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 ArchAstro 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. ### 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 archastro 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 ArchAstro resource `id` is a different identifier and must not be substituted. ### Option A: connect from the portal The portal and API use the same `SlackChannelBinding` resource. If your app exposes the network connection UI, open the network's **Connection** tab, select **Connect Slack channel**, enter the Slack channel ID, and choose the resident agent. ### Option B: connect from the CLI ```bash archastro 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 archastro list slackchannelbindings --team archastro describe slackchannelbinding \ --slack-team ``` Remove the binding: ```bash archastro 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 ArchAstro 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 archastro 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. --- ## 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` | ArchAstro 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 archastro update agent \ --name "BigQuery Buddy" \ --lookup-key bigquery-buddy ``` Optionally update its Slack-facing avatar at the same time: ```bash archastro 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 ArchAstro 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 ArchAstro 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 ArchAstro. 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 archastro describe agentinstallation archastro 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 ArchAstro permissions to perform the assignment. ### Users cannot see the mirrored conversation Slack and ArchAstro 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 [Organizations](/docs/collaborate/organizations) for the ownership and permission boundary behind integrations. 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.archastro.ai/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 Developer 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 Developer Portal. The most useful categories are: ### Thread events | Event | Description | |-------|-------------| | `thread.created` | A new thread was created | | `message.created` | 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, ArchAstro 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 archastro list automationruns --automation aut_abc123 archastro list automationruns --automation aut_abc123 --status failed archastro 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). - 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 archastro list automations archastro list automations --type trigger # Create archastro create automation -n "Nightly Report" -t scheduled --schedule "0 0 * * *" --config-id cfg_abc123 # Manage state archastro activate automation aut_abc123 archastro pause automation aut_abc123 # Update archastro update automation aut_abc123 -n "Updated Name" --config-id cfg_def456 # Delete archastro delete automation aut_abc123 # View runs archastro list automationruns --automation aut_abc123 archastro describe automationrun atr_abc123 ``` --- ## Design patterns ### Event-driven onboarding Trigger shared onboarding work when a new user joins a thread: ```bash archastro 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 archastro 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 archastro create automation -n "Ingestion Failure Alert" \ -t trigger \ --trigger context.ingestion.failed \ --config-id cfg_ingestion_alert ``` --- ### Scripts URL: https://latest.docs.archastro.ai/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 ArchAstro 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` - **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`. See the [Script Language Reference](/docs/build-agents/script-reference) for the full list of namespaces and functions. --- ## 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 } ``` --- ## Validation The CLI validates script syntax with `archastro 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 `archastro configs sample script`. 2. Write the custom logic in your local file. 3. Validate with `archastro validate configs -k script -f ./path/to/script.yaml`. 4. Deploy with `archastro configs deploy`. 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 archastro script validate -f ./path/to/script.yaml archastro script run -f ./path/to/script.yaml --input '{"key": "value"}' archastro script docs ``` `archastro script docs` 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 archastro test script math-tests ``` Run an on-disk test file before or after deploying it: ```bash archastro 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 app, with a non-zero exit code on failure for CI: ```bash archastro test scripts archastro --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 archastro 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 `archastro 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. --- ### Script Language Reference URL: https://latest.docs.archastro.ai/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 `archastro describe scriptdocs`. # ArchAstro 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.archastro.ai/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 app 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 ArchAgents. 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 ArchAstro app you can already access. - The local plugin reaches the agent through private endpoints scoped to that app. - 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 archastro 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 Developer 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 app has a single agent, the command picks it; if several are available, the command walks you through an interactive selection. To target a different ArchAstro app, 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) archastro embed start # show the active session archastro embed status # list the active agent's tools and skills archastro embed list tools archastro embed list skills # install a linked skill into the local coding harness archastro embed install skill # execute one of the active agent's tools by ID, lookup key, or builtin tool key archastro embed run tool # refresh local state after upstream changes archastro embed sync # end the session archastro 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. [ArchAgents](https://docs.archagents.com/docs/collaborate/agent-network): the cross-company boundary model behind the example above. --- ### Tools URL: https://latest.docs.archastro.ai/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 | | `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 archastro list agenttools --agent archastro 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 archastro create agenttool --agent \ --kind builtin \ --builtin-tool-key search \ -k support-search ``` Then activate it: ```bash archastro 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 archastro 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 archastro activate agenttool ``` That pattern is useful because the workflow stays visible and reviewable, while the agent gets a clean action surface. ## 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 archastro 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 archastro update agenttool --description "Updated description" archastro pause agenttool archastro 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 [Skills](/docs/build-agents/skills) for reusable coding-agent behavior linked to agents. 2. Read [Embed](/docs/operate-agents/embed) for the best local testing loop. 3. Read [Computer Use](/docs/operate-agents/computer-use) when the capability needs a managed workstation instead of a simple tool call. --- ### Skills URL: https://latest.docs.archastro.ai/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 ArchAstro 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 archastro list skills archastro describe skill ``` Create one directly: ```bash archastro 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 archastro describe skillfile incident-review SKILL.md archastro create skillfile incident-review references/checklist.md --file ./references/checklist.md archastro 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 archastro configs deploy ``` Pull the live state into local files: ```bash archastro configs sync ``` 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 archastro describe skill incident-review archastro create agentskill --agent --config archastro 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 archastro 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 archastro describe skill archastro 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 archastro 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 archastro 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. --- ### Secrets URL: https://latest.docs.archastro.ai/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 app 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 | app 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 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) archastro list agentenvvars --agent # create one archastro 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) archastro update agentenvvar --value sk_live_rotated_... # update only the description archastro update agentenvvar --description "Rotated 2026-05-05" # inspect one secret archastro describe agentenvvar # remove archastro 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 archastro 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 archastro 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 archastro 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.** `archastro 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. --- ### Installations URL: https://latest.docs.archastro.ai/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. 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 app. Kinds vary by app and can change over time, so always check before scripting: ```bash archastro list agentinstallationkinds ``` --- ## Inspect available kinds Before you attach anything, inspect the kinds the platform supports for the current app: ```bash archastro 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 archastro 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 archastro list agentinstallations --agent archastro 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 archastro 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 archastro 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 ArchAstro. 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 the [developer portal](https://developers.archastro.ai) as an org admin - Open your app and go to the **My Org** page - In the **Integrations** panel, 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 archastro 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 archastro list integrations --provider github_app --auth-type app_installation --org archastro 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. --- ### Computer Use URL: https://latest.docs.archastro.ai/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 archastro list agentcomputers --agent archastro create agentcomputer --agent -n "ops-workstation" archastro describe agentcomputer archastro refresh agentcomputer archastro 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. --- ### Extensions & Integrations URL: https://latest.docs.archastro.ai/docs/more/extensions-integrations Summary: Connect agents to outside systems through built-in integrations, custom tools, MCP servers, webhooks, and scripts. ## Overview ArchAstro 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 ArchAstro | | **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 ArchAstro 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 archastro create agentinstallation --agent --kind integration/github archastro authorize agentinstallation archastro 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: archastro 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 ArchAstro 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 archastro 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 ArchAstro supports connecting to remote [MCP (Model Context Protocol)](https://modelcontextprotocol.io) servers. This lets agents use any tool from the MCP ecosystem — Stripe, Notion, Sentry, Linear, and hundreds of others. MCP servers are defined as configs: ```yaml kind: MCPServer key: stripe-mcp name: Stripe url: https://mcp.stripe.com auth: type: bearer token_source: integration ``` When an MCP server is connected with an integration credential, the agent gets access to all the tools that server exposes — without you writing any custom tool definitions. --- ## Webhooks Inbound webhooks let external systems trigger agent behavior. When ArchAstro 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. --- ## The API Everything in ArchAstro is API-first. The same operations available in the CLI and portal are available through the REST API: - Create and manage agents, teams, threads, and messages - Deploy configs and manage installations - Send messages and trigger agent behavior programmatically See the [API Reference](/openapi.json) for the full specification. --- ## 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` | | Build a product on top of ArchAstro | REST API | Start with built-in integrations for supported services. Use custom tools or scripts when you need something specific to your business. --- ### CLI URL: https://latest.docs.archastro.ai/docs/start-here/cli Summary: The terminal workflow for building and operating agents. ## Overview The ArchAstro 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 `archastro 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 `archastro --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 ArchAstro 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/archastro ``` ### Linux ```bash curl -fsSL https://archastro.ai/install.sh | bash ``` ### Windows ```powershell irm https://archastro.ai/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 archastro --help ``` ## 2. Sign in ```bash archastro auth login archastro auth status ``` The CLI opens a browser so you can sign in and authorize the local session. Use `archastro auth logout` when you want to clear the current session. --- ## 3. Connect the current project ```bash cd my-project archastro init ``` `archastro init` connects the current directory to ArchAstro and writes an `archastro.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 ArchAstro 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 archastro list agentsamples archastro 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 archastro 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 `archastro help models` or `archastro 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 archastro 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 archastro create agentsession --agent \ --instructions "Help a user resolve billing questions. Ask one clarifying question if needed." archastro exec agentsession \ -m "How should we handle invoice failures?" ``` If you want the agent to react automatically inside the product, add a routine: ```bash archastro create agentroutine --agent \ -n "Reply to new messages" \ -e message.created \ -t script \ --script "{ handled: true }" archastro activate agentroutine ``` `message.created` 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 `archastro 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 `message.created` 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 archastro create thread -t "Support" --owner-type agent --owner-id ``` Create or reuse a user who will send the test message: ```bash archastro 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 archastro create threadmember --thread --user ``` Then send a message: ```bash archastro 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: archastro auth login ``` Fix: ```bash archastro auth login archastro auth status ``` ### The current repo is not linked ```text No archastro.json found. Run: archastro init ``` Fix: ```bash archastro init ``` ### The project is linked, but the token is missing ```text No token for this project. Run: archastro auth login ``` Fix: ```bash archastro auth login ``` --- ## Common workflows ### Inspect and manage agents ```bash archastro list agents archastro describe agent archastro update agent -n "Senior Support Agent" archastro 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 archastro list threads archastro describe thread archastro list threadmembers --thread archastro list threadmessages --thread archastro 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 archastro list agentcomputers --agent archastro create agentcomputer --agent -n "dev" archastro 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 archastro list contextsources archastro list contextingestions --status failed # Inspect installations and tool attachments archastro list agentinstallations --agent archastro list agenttools --agent # Inspect durable memory archastro 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 ArchAstro plugins for you in one step: ```bash archastro 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 ArchAstro 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 `archastro setup` and a harness restart. ### Work with config files ```bash archastro configs sync archastro configs deploy mkdir -p ./tmp archastro configs sample workflow --to-file ./tmp/workflow.sample.yaml archastro validate configs -k workflow -f ./tmp/workflow.sample.yaml archastro configs sample ``` 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 ArchAstro: 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 archastro list agents archastro describe agent archastro create agent -n "Support Agent" archastro update agent -n "New Name" archastro delete agent ``` ### Users ```bash archastro list users archastro describe user archastro create user -e alice@example.com -n "Alice" archastro create user --system-user -n "Demo User" archastro delete user ``` ### Teams ```bash archastro list teams archastro describe team archastro create team -n "Engineering" archastro update team -n "New Name" archastro delete team ``` ### Threads ```bash archastro list threads archastro describe thread archastro create thread -t "Project thread" --user archastro create threadmember --thread --agent archastro 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 archastro list automations archastro describe automation archastro create automation -n "Daily Report" -t scheduled --schedule "0 8 * * *" archastro activate automation archastro pause automation archastro delete automation ``` ### Knowledge ```bash archastro list integrations archastro list contextsources archastro list contextingestions --status failed archastro list contextitems --source ``` ### Tools ```bash archastro list agenttools --agent archastro describe agenttool archastro create agenttool --agent --kind builtin --builtin-tool-key search archastro activate agenttool ``` ### Installations ```bash archastro list agentinstallationkinds archastro list agentinstallations --agent archastro create agentinstallation --agent --kind web/site --config '{"url":"https://example.com"}' archastro describe agentinstallation ``` ### Embed Install the local plugin from your terminal, then invoke embed inside your coding agent: ```bash archastro setup ``` ```text # Claude Code /embed # Codex $embed # Cursor @archagents embed ``` ### Skills ```bash archastro list skills archastro describe skill archastro create skill -n "Incident Review" --file ./skills/incident-review/SKILL.md archastro describe skillfile incident-review SKILL.md ``` ### Memory and routine runs ```bash archastro list agentworkingmemory --agent archastro list agentroutineruns --routine archastro list automationruns --automation ``` ### Files and project setup ```bash archastro list files ``` Use Developer Portal for domains, webhooks, and other project-level setup that does not need to live in your terminal workflow. ### Configs ```bash archastro configs init archastro configs kinds archastro configs sync archastro configs deploy archastro configs sample mkdir -p ./tmp archastro configs sample workflow --to-file ./tmp/workflow.sample.yaml archastro 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 archastro script validate -f ./path/to/script.yaml archastro script run -f ./path/to/script.yaml --input '{"key": "value"}' archastro script docs ``` ### 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 archastro list sandboxes archastro describe sandbox archastro create sandbox -n "Staging" -s staging archastro activate sandbox archastro 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 archastro list agents --json | jq -r '.data[].id' USER_ID=$(archastro create user -e bot@example.com --system-user --json | jq -r '.id') archastro list teams --json | jq '.data[] | select(.name | contains("Eng"))' ``` Because `--json` is global, `archastro --json create user...` works too. Use whichever placement you prefer, but keep it consistent inside a script. --- ## Shell completion ```bash eval "$(archastro completion bash)" eval "$(archastro completion zsh)" archastro completion fish | source ``` --- ## Project files | File | Purpose | |------|---------| | `./archastro.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 (`archastro astrodev`), plan mode, sessions, and headless `--print`. 3. [Astrorun](/docs/start-here/astrorun): local discovery, processing, and persisted review records for agent work (`archastro astrorun`). 4. [Use ArchAstro 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.archastro.ai/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 ArchAstro 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 resource and the local `configs/` workflow are related but different: - `archastro config...` works with live config objects directly - `archastro configs...` manages the local file-backed sync and deploy loop 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 archastro configs init ``` Then inspect the kinds the project supports: ```bash archastro configs kinds archastro configs sample agent archastro configs sample 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 `archastro help models` when you need another provider. When you want to pull the current project state into local files: ```bash archastro configs sync ``` When you are ready to push reviewed changes back: ```bash archastro configs deploy ``` 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 archastro list configs --kind workflow archastro describe config archastro configs 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 archastro configs sample workflow --to-file ./tmp/workflow.sample.yaml archastro 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 compare it to the live object before you deploy: ```bash archastro describe config archastro configs content ``` That keeps the local file and the live platform object in the same review loop. --- ## 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 `archastro configs sample workflow` 2. edit the workflow file locally 3. validate before deploy 4. run `archastro configs deploy` 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.archastro.ai/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 ArchAstro 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 ArchAstro working in this repo and put my first agent live. 1) Install the ArchAstro CLI. macOS: brew install ArchAstro/tools/archastro. Linux/Windows: see https://docs.archastro.ai/docs/start-here/getting-started. 2) Run these in order, asking me for anything missing: archastro setup archastro auth login archastro 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.archastro.ai/llms-full.txt. ``` --- ## What the four commands actually do | Command | What it does | |---|---| | `archastro setup` | Installs the ArchAstro plugin into Claude Code, Codex, and Cursor. Idempotent. | | `archastro auth login` | Opens a browser to complete sign-in and writes a session token for the CLI. | | `archastro 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.archastro.ai` | | Developer Portal | `https://developers.archastro.ai` | | LLM index (short) | `https://docs.archastro.ai/llms.txt` | | LLM index (extended) | `https://docs.archastro.ai/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 `archastro 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 `archastro 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: {} 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 `archastro help models` or `archastro list aimodels` before inventing a model string. For everything else, see [Agents](/docs/build-agents/agents) and use `archastro --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 `archastro --help`, `archastro --help`, and `archastro help models` to discover flags and model IDs. Don't guess. 5. Use [`llms-full.txt`](https://docs.archastro.ai/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.archastro.ai/docs/build-agents/samples Summary: End-to-end playbooks that combine the portal 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 shows up where the product actually expects it. 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-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=$(archastro --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 `archastro describe ...` or `archastro 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: `archastro --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 ArchAstro 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 (`archastro auth login`). 2. A project is linked (`archastro init`). ### Run in the CLI ```bash archastro auth login archastro init agent_id=$(archastro --json create agent -n "Support Agent" -k support-agent \ -i "You help users solve billing and support problems clearly." | jq -r '.id') session_id=$(archastro --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') archastro exec agentsession "$session_id" \ -m "A customer says their invoice failed and wants to know what to try next." archastro describe agentsession "$session_id" --follow user_id=$(archastro --json create user --system-user -n "Support Test User" | jq -r '.id') thread_id=$(archastro --json create thread -t "Support test thread" \ --owner-type agent --owner-id "$agent_id" --skip-welcome-message | jq -r '.id') archastro create threadmember --thread "$thread_id" --user "$user_id" archastro create threadmessage --thread "$thread_id" --user "$user_id" \ -c "Can you help me figure out why my invoice keeps failing?" --wait routine_id=$(archastro --json create agentroutine --agent "$agent_id" \ -n "billing-triage" \ -e message.created \ -t script \ --script "{ handled: true }" | jq -r '.id') archastro 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 archastro configs init archastro configs kinds archastro configs sample agent archastro configs sync archastro configs deploy ``` ### 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 - ArchAstro 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 `archastro configs sample workflow` as a starting point) with a script node for the custom logic. Deploy it with `archastro configs deploy` 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=$(archastro --json create automation \ -n "Daily support summary" \ -t scheduled \ --schedule "0 9 * * 1-5" \ --config-id | jq -r '.id') archastro activate automation "$automation_id" archastro list automations archastro describe automation "$automation_id" archastro 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 app 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=$(archastro --json create sandbox -n "Notification Test" -s notification-test | jq -r '.id') archastro activate sandbox archastro list sandboxes archastro describe sandbox "$sandbox_id" user_id=$(archastro --json create user --system-user -n "Sandbox Notification User" | jq -r '.id') thread_id=$(archastro --json create thread -t "Sandbox notification test" \ --user "$user_id" --skip-welcome-message | jq -r '.id') archastro create threadmember --thread "$thread_id" --user "$user_id" archastro create threadmessage --thread "$thread_id" --user "$user_id" \ -c "Trigger the sandbox notification path." --wait archastro list sandboxmails --sandbox "$sandbox_id" ``` ### What to check - the CLI is operating in the sandbox context after `archastro 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) --- ## Cross-company samples Coordinating a rollout across two companies and debugging a cross-company integration are cross-company workflows, so they live in ArchAgents — see the [ArchAgents docs](https://docs.archagents.com/docs/collaborate/agent-network). --- ## Sample 5: 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: {} 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 archastro validate configs --kind AgentTemplate --file configs/agents/security-reviewer.yaml archastro 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=$(archastro --json create agentsession --agent \ --instructions "Review code for security issues." | jq -r '.id') archastro 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=$(archastro --json create thread -t "Security review" \ --owner-type agent --owner-id --skip-welcome-message | jq -r '.id') user_id=$(archastro --json create user --system-user -n "Engineer" | jq -r '.id') archastro create threadmember --thread "$thread_id" --user "$user_id" archastro 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 archastro activate sandbox staging archastro deploy agent configs/agents/security-reviewer.yaml --name "Security Reviewer" # test in sandbox... # When ready, switch back to production and deploy archastro activate sandbox # (select production from the interactive prompt, or deactivate the sandbox) archastro 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.archastro.ai/docs/start-here/astrodev Summary: A local coding agent for interactive or headless work — run standalone or embed a live ArchAstro agent with its identity, tools, and skills. ## Overview AstroDev is the coding agent that ships with the ArchAstro 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 `archastro` command. Two things make it fit ArchAstro: 1. **It can embed a live agent.** Pick an agent from your linked app. 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 `archastro 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 ArchAstro 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 archastro init archastro 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 archastro 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 archastro astrodev support-agent archastro 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 archastro 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 archastro astrodev -p "Summarize the uncommitted diff" archastro astrodev -p "List failing tests" --output-format json --max-turns 8 archastro astrodev -p "Investigate this support issue" \ --agent support-agent --model --output-format json archastro 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 archastro astrodev provider list archastro astrodev provider status archastro astrodev provider login openai archastro astrodev provider login xai --api-key sk-… archastro 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) | | **Developer 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 archastro 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 archastro 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 archastro auth status # non-interactive token already configured archastro 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 ArchAstro 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.archastro.ai/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 ArchAstro 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 archastro init archastro 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 archastro 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 archastro astrorun attach archastro 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/archastro/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 archastro 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 archastro 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: - `archastro 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 `archastro astrorun attach` to inspect recorded sessions, reattach and exit the harness, press `e` from the dashboard, or use `archastro 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/archastro/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 | | **Developer 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 archastro 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 `archastro 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 `archastro 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. - Prefer API reference and setup docs for implementation details. - Ask for missing environment variables before destructive operations.