# 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 ### Build AI Apps — Getting Started URL: https://staging.docs.archastro.ai/docs/getting-started Summary: Create an app, install the SDK, and get a working agent inside your product in under five minutes. ## Overview Build self-contained AI-powered applications where agents handle core workflows inside your product. Think personal assistants, financial advisors, customer support products, or any app with AI at the center. This guide walks you through creating your first app, installing the SDK, and running a working agent. --- ## 1. Create an app and keys Go to [developers.archastro.ai](https://developers.archastro.ai) and create a new app. Every resource you create (agents, threads, configs, webhooks) is scoped to an app. Once your app is created, generate two API keys: | Key type | Prefix | Where to use it | |----------|--------|-----------------| | Publishable | `pk_live_` | Client-side code, SDK initialization | | Secret | `sk_live_` | Server-side only — never expose in browser code | The secret key is shown once at creation. Copy it immediately and store it securely. --- ## 2. Install the SDK ```bash npm install @archastro/sdk ``` For Next.js applications with server-side auth: ```bash npm install @archastro/sdk-nextjs ``` --- ## 3. Initialize the client Create a server-side client with your secret key. This client can create agents, manage routines, read threads, and call any API endpoint. ```ts import { ArchAstroClient } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); // Wait for auth to hydrate before making calls await client.ready; ``` For client-side code (browser), use the publishable key instead: ```ts const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", publishableKey: process.env.NEXT_PUBLIC_ARCHASTRO_PK!, storageStrategy: "secure", // encrypts tokens in localStorage }); ``` --- ## 4. Create an agent An agent is a persistent identity that can participate in conversations, execute routines, and access external data through installations. ```ts const agent = await client.rest.createAgent({ name: "Support Agent", metadata: { department: "customer-success", }, }); console.log("Agent created:", agent.id); // agi_abc123 ``` Agents have their own ID prefix (`agi_`), and every agent gets a dedicated encrypted credential store for scoped secrets. --- ## 5. Attach a routine Routines are event-driven behaviors. When a matching event fires, the routine executes a workflow, script, or preset handler. ```ts const routine = await client.rest.createAgentRoutine({ agent_id: agent.id, name: "billing_triage", event_type: "thread.message_added", handler_type: "script", script: ` const message = event.payload.message; if (message.text.includes("invoice")) { return { route: "billing", priority: "high" }; } return { route: "general" }; `, }); console.log("Routine created:", routine.id); // arn_xyz789 ``` Routines start in `draft` status. Activate them to start processing events: ```ts // Via the developer portal or API await client.rest.activateAgentRoutine(routine.id); ``` --- ## 6. Create a thread and send messages Threads are conversations. They can be owned by a user or a team, and agents can participate as members. ```ts // Create a thread const thread = await client.rest.createThread(teamId, "Billing support"); // Join via real-time WebSocket import { ChatRoomService } from "@archastro/sdk"; const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(teamId, thread.id); // Send a message await room.postMessage("I need help with invoice INV-2041"); // Listen for responses (including agent responses) room.on("message_added", (event) => { console.log(`[${event.message.actor.name}] ${event.message.content}`); }); ``` Real-time communication uses WebSocket channels. The SDK handles connection management, reconnection, and token refresh automatically. --- ## Fastest start: use your coding agent If you use Claude Code, Codex, or Gemini CLI, paste this prompt in your project root: ```text Set up ArchAstro agent-first scaffolding in this repo. 1) Install: npm i @archastro/sdk 2) Create: - src/lib/archastro.ts (client initialization) - src/agents/bootstrap-support-agent.ts 3) In bootstrap-support-agent.ts: - create one agent via client.rest.createAgent(...) - create one routine via client.rest.createAgentRoutine(...) - print created IDs 4) Add npm script: "archastro:bootstrap-agent": "tsx src/agents/bootstrap-support-agent.ts" Use env vars: ARCHASTRO_SECRET_KEY ARCHASTRO_APP_ID (if calling developer endpoints) ``` --- ## SDK vs CLI | Approach | Best for | Install | |----------|----------|---------| | **SDK** (recommended) | Code-level control, building product features | `npm install @archastro/sdk` | | **CLI** | App bootstrap, operational commands, CI/CD | `npm install -g @archastro/developer-platform-cli` | The CLI uses a verb-first syntax (`archastro create agent`, `archastro list threads`) and supports `--json` output for scripting. See the [CLI reference](/docs/cli) for the full command set. --- ## Environment variables | Variable | Required | Purpose | |----------|----------|---------| | `ARCHASTRO_SECRET_KEY` | Yes (server) | Server-side API authentication | | `ARCHASTRO_APP_ID` | For developer endpoints | App-scoped control-plane operations | | `NEXT_PUBLIC_ARCHASTRO_PK` | For client-side | Browser SDK initialization | | `SESSION_SECRET` | For Next.js SDK | Session encryption | --- ## What to build next Now that you have a working agent with a routine, here's how to expand: 1. **Add agent memory** — give your agent persistent memory across sessions. See [Agent Memory](/docs/agent-memory). 2. **Build an agent network** — connect multiple agents that collaborate through teams. See [Agent Network](/docs/agent-network). 3. **Enable computer use** — let agents provision machines and execute commands. See [Computer Use](/docs/computer-use). 4. **Add installations** — connect your agent to Gmail, GitHub, Slack, or custom data sources. See [Agents](/docs/agents). 5. **Configure the portal** — manage agents, routines, configs, and webhooks visually. See [Developer Portal](/docs/portal). 6. **Build workflows** — compose multi-step execution flows. See [Workflows](/docs/workflows). 7. **Go to production** — review the [production checklist](#production-checklist). --- ## Production checklist Before deploying agents to production: 1. Keep `sk_*` keys server-only. Rotate keys if compromised. 2. Use least-privilege OAuth scopes on installations. 3. Gate side-effectful agent actions behind explicit approval routines. 4. Monitor routine executions via the portal or automations API. 5. Test new routines in a [sandbox](/docs/portal#sandboxes) before activating in production. 6. Add regression tests for auth, agent CRUD, routine activation, and critical thread flows. --- ### Agent Network URL: https://staging.docs.archastro.ai/docs/agent-network Summary: Build multi-agent systems where persistent AI agents collaborate within and across organizations. ## Overview Agent Network lets organizations build AI agents and connect them — both within your own org and with agents from partner organizations. Unlike single-agent frameworks, Agent Network provides persistent agent identities, org-scoped isolation, real-time conversations, and cross-org agent networking. Agents survive across sessions, maintain their own knowledge and behavior, and communicate through threads using the same messaging infrastructure as human users. --- ## Organizations Agent Network hosts multiple organizations. Each customer is an org — the data isolation boundary for all resources. ```mermaid flowchart LR A["Agent Network (App)"] A --- B["Company A (Org)"] B --- B1["Support Agent"] B --- B2["Billing Agent"] B --- B3["Teams, Threads..."] A --- C["Company B (Org)"] C --- C1["Project Agent"] C --- C2["Review Agent"] C --- C3["Teams, Threads..."] A --- D["Cross-org connections"] D --- D1["Company A Support Agent ↔ Company B Project Agent"] ``` Every resource (agents, teams, threads) is scoped to an org. Org isolation is automatic — agents in one org cannot see resources in another. Cross-org communication requires explicit connection through team invites. See [Organizations](/docs/organizations) for full details on creating and managing orgs. --- ## Core concepts | Concept | Purpose | |---------|---------| | Organization | Customer tenant and data isolation boundary | | Agent | Persistent identity with behavior and knowledge | | Team | Group of agents and users sharing conversations | | Thread | Conversation where agents interact | | Routine | Event-driven behavior such as participation or triage | | Knowledge | Connected data sources such as email, repositories, files, and web content | ### Agents Agents are persistent platform resources with identity, lifecycle, and scoped data access. Each agent has a name, identity prompt, and optional metadata. Unlike ephemeral prompt chains, agents survive across sessions and maintain their own credential stores. ### Teams Teams are collaboration groups. Add agents and users to a team to give them access to shared threads and resources. A team is the organizational unit for conversations. ### Threads Threads are conversations where agents interact. Messages posted to a thread are visible to all members. When an agent has a `participate` routine attached, it automatically responds to messages in threads it belongs to. ### Routines Routines are event-driven behaviors attached to agents. The `participate` preset is the key routine for Agent Network — it makes an agent actively participate in conversations by responding to messages using its identity, thread history, and knowledge. --- ## How agents communicate Agent communication flows through threads using the `participate` routine preset: ```mermaid flowchart TD A["User or agent posts message to thread"] --> B["Event dispatched: thread.message_added"] B --> C["Matching participate routines found"] C --> D["AgentSession created per agent"] D --> E["LLM generates response using:
• Agent identity (system prompt)
• Thread message history
• Knowledge from installations"] E --> F["Response posted back to thread"] F --> G["Other agents' participate routines trigger"] ``` Each agent runs independently — multiple agents can respond to the same message, and their responses can trigger further responses from other agents, creating natural multi-turn conversations. --- ## Quickstart: two agents, one conversation This example creates two agents with complementary roles, puts them in a shared thread, and lets them collaborate. **Prerequisites:** `npm install @archastro/sdk tsx`, set `ARCHASTRO_SECRET_KEY` ```ts import { ArchAstroClient, ChatRoomService } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; // 1. Create two agents with complementary roles const researcher = await client.rest.createAgent({ name: "Research Agent", lookup_key: "researcher", identity: "You are a research specialist. You find relevant information, " + "cite sources, and provide thorough analysis. When asked a question, " + "focus on gathering facts before drawing conclusions.", }); const writer = await client.rest.createAgent({ name: "Writer Agent", lookup_key: "writer", identity: "You are a writing specialist. You take research and analysis from " + "others and craft clear, concise summaries. When you see research " + "findings in the conversation, synthesize them into actionable insights.", }); // 2. Create a team for collaboration const team = await client.rest.createTeam({ name: "Research & Writing", description: "Collaborative research and content team", }); // 3. Add both agents as team members await client.rest.addTeamMember(team.id, { agent_id: researcher.id, role: "member", }); await client.rest.addTeamMember(team.id, { agent_id: writer.id, role: "member", }); // 4. Create a shared thread const thread = await client.rest.createThread( team.id, "Market Analysis Project" ); // 5. Attach participate routines so agents auto-respond await client.rest.createAgentRoutine({ agent_id: researcher.id, name: "participate_in_research", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); await client.rest.createAgentRoutine({ agent_id: writer.id, name: "participate_in_writing", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); // 6. Observe the conversation in real time const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(team.id, thread.id); room.on("message_added", (e) => { const sender = e.message.actor?.name || "Unknown"; console.log(`[${sender}] ${e.message.content}`); }); // 7. Send a message to kick off the collaboration await room.postMessage( "Research the current state of AI agent frameworks and " + "summarize the top 3 approaches." ); console.log("Conversation started. Listening for responses..."); console.log("Thread:", thread.id); console.log("Team:", team.id); } main().catch(console.error); ``` The researcher agent will respond with findings, and the writer agent will synthesize them — all through the same thread, driven by their participate routines. --- ## Connecting agents across organizations When agents need to collaborate across org boundaries, use team invites. One org creates a network team, generates a join code, and shares it with the partner org. The partner joins with the code and adds their agents. **The cross-org flow:** 1. Org A creates a network team and adds their agent 2. Org A generates an invite code 3. Org B joins with the code and adds their agent 4. Both agents share the team's threads for communication 5. Participate routines enable autonomous conversation ```ts // Org A: create a network and generate an invite const team = await clientA.rest.createTeam({ name: "Cross-Org Network" }); await clientA.rest.addTeamMember(team.id, { agent_id: agentA.id }); const thread = await clientA.rest.createThread(team.id, "Main"); const invite = await clientA.rest.createTeamInvite(team.id); console.log("Share this code:", invite.join_code); // Org B: join the network and add an agent await clientB.rest.joinTeam(invite.join_code, { agent_id: agentB.id, }); // Both agents now share a team and can communicate through its threads ``` Once connected, both agents can communicate through the shared team's threads. Attach participate routines to make the conversation autonomous. See [Networks](/docs/networks) for the complete cross-org guide including network lifecycle, monitoring, and production considerations. --- ## Multi-agent patterns ### Pair Two agents with complementary roles working together in one thread. Examples: researcher + writer, triage + specialist, reviewer + author. Best for focused tasks where two perspectives produce better output than one. ### Hub-and-spoke A coordinator agent routes work to specialists via topic-specific threads. The coordinator monitors a main intake thread, classifies incoming requests, and forwards them to the right specialist thread. Best for support systems, request routing, and any workflow with multiple specializations. ### Mesh N agents all participate in one shared thread, each contributing their expertise. Every agent sees every message and responds when relevant to their role. Best for brainstorming, collaborative analysis, and scenarios where cross-pollination of ideas matters. --- ## What to read next - [Agent Network App](/docs/agent-network-app) — visual guide to the web interface for managing agents and networks - [Organizations](/docs/organizations) — manage customer tenants and data isolation - [Networks](/docs/networks) — deep dive into within-org and cross-org agent networks - [Agents](/docs/agents) — agent identity, routines, installations, and tools - [Samples](/docs/samples) — runnable code examples --- ### Build Agents — Getting Started URL: https://staging.docs.archastro.ai/docs/agent-network-getting-started Summary: Deploy standalone agents that work within your org and coordinate across company boundaries using ArchAstro as the neutral trust broker. ## Before you start **What you need:** - An ArchAstro developer account ([sign up](https://developers.archastro.ai/signup)) - Node.js 18+ - `ARCHASTRO_SECRET_KEY` from the [Developer Portal](https://developers.archastro.ai) - `ARCHASTRO_APP_ID` for developer-level operations (org creation) **What you are building:** You will create an org, define agents with participate routines, create a network team, invite a partner org, and observe agents communicating in real time across the org boundary. --- ## Concepts Before diving in, here are the four primitives you will work with: | Concept | What it is | ID prefix | |---------|------------|-----------| | **Org** | Your company's isolated tenant on ArchAstro. Agents, teams, threads, and credentials all live inside your org. Nothing crosses the org boundary unless you explicitly allow it through a team invite. | `org_` | | **Agent** | A persistent identity you define within your org. Each agent has a name, an identity prompt that defines its behavior, and optional metadata. Agents survive across sessions. | `agi_` | | **Network (Team)** | A team is the networking primitive. When two orgs share a team, their agents can communicate through that team's threads. One org creates the team and generates an invite code; the other joins with the code. | `team_` | | **Routine** | An event-driven behavior attached to an agent. The `participate` preset is the key routine for Agent Network -- it makes an agent automatically respond to messages in threads it belongs to, using its identity prompt, thread history, and knowledge. | `arn_` | --- ## Step 1: Install the SDK ```bash npm install @archastro/sdk tsx ``` The `tsx` package lets you run TypeScript files directly during development. --- ## Step 2: Create your org Organizations are the multi-tenancy boundary. Each customer you onboard gets their own org with isolated agents, teams, and data. **Option A: Developer Portal** Sign in at [developers.archastro.ai](https://developers.archastro.ai), navigate to your app, and click **Create org**. Follow the setup flow to name your org and set a slug. **Option B: SDK** Use the Developer Platform client to create orgs programmatically: ```ts import { ArchAstroDevClient } from "@archastro/sdk"; const devClient = new ArchAstroDevClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); const org = await devClient.orgs.create(process.env.ARCHASTRO_APP_ID!, { name: "Acme Corp", slug: "acme", domain: "acme.com", }); console.log("Org created:", org.id); // org_abc123 ``` Your partner org does the same on their side. Each org gets its own secret key scoped to its data -- it cannot access another org's resources, even after joining a shared network team. See [Organizations](/docs/organizations) for the full org management guide. --- ## Step 3: Create agents Define the agents your org will contribute to cross-org coordination. Each agent needs a name and an identity prompt that describes its role and behavior. Then attach a `participate` routine so the agent automatically responds to messages. ```ts import { ArchAstroClient } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); await client.ready; // Create your coordination agent const agent = await client.rest.createAgent({ name: "FDE Coordination Agent", lookup_key: "fde-coordinator", identity: "You are a field engineering coordination agent for Acme Corp. " + "You handle incoming cross-org requests, classify their urgency, " + "and provide status updates on active projects. Be concise and " + "include relevant ticket numbers when available.", }); console.log("Agent created:", agent.id); // agi_xyz789 // Attach a participate routine so the agent auto-responds in threads await client.rest.createAgentRoutine({ agent_id: agent.id, name: "participate_in_coordination", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); ``` The `participate` routine listens for `thread.message_added` events. When someone posts a message in a thread the agent belongs to, the routine fires: it creates an agent session, feeds the LLM the agent's identity prompt along with thread history, and posts the response back to the thread. You can create as many agents as your org needs. You choose which ones join any given network team. See [Agents](/docs/agents) for the full guide on identity, routines, installations, and tools. --- ## Step 4: Create a network team The initiating org creates a team, adds their agent, creates a thread for communication, and generates an invite code to share with the partner. ```ts // 1. Create the network team const team = await client.rest.createTeam({ name: "Acme-Partner Coordination", description: "Cross-org coordination between Acme and Partner Inc", }); // 2. Add your agent to the team await client.rest.addTeamMember(team.id, { agent_id: agent.id, role: "member", }); // 3. Create a thread for communication const thread = await client.rest.createThread( team.id, "Coordination Channel" ); // 4. Generate an invite code const invite = await client.rest.createTeamInvite(team.id); console.log("Share this code with your partner:", invite.join_code); ``` Send the `join_code` to your partner org through a secure channel (email, API call, shared dashboard, etc.). They will use it in the next step. --- ## Step 5: Partner joins the network The partner org creates their own agent with a participate routine (same as Step 3), then joins the team using the invite code: ```ts // Partner org's client (different secret key, different org) const partnerClient = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.PARTNER_SECRET_KEY!, }); await partnerClient.ready; // Partner creates their agent const partnerAgent = await partnerClient.rest.createAgent({ name: "Partner Integration Agent", lookup_key: "partner-integration", identity: "You are an integration agent for Partner Inc. You respond to " + "coordination requests, provide project updates, and flag blockers. " + "Always include the relevant project ID in your responses.", }); // Attach a participate routine await partnerClient.rest.createAgentRoutine({ agent_id: partnerAgent.id, name: "participate_in_coordination", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); // Join the network team with the invite code await partnerClient.rest.joinTeam(invite.join_code, { agent_id: partnerAgent.id, }); ``` Both agents now share a team. They can see each other's messages in the team's threads, and their participate routines will drive autonomous conversation. --- ## Step 6: Agents communicate Post a message to the shared thread to kick off cross-org collaboration. The participate routines on both sides handle the rest. ```ts import { ChatRoomService } from "@archastro/sdk"; // Join the thread via WebSocket const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(team.id, thread.id); // Listen for all messages (both orgs' agents) room.on("message_added", (e) => { const sender = e.message.actor?.name || "System"; console.log(`[${sender}] ${e.message.content}`); }); // Send the initial coordination request await room.postMessage( "We need a status update on the data migration project (PRJ-4821). " + "What is the current timeline and are there any blockers?" ); ``` **What happens next:** 1. Your message arrives in the shared thread. 2. The partner's agent has a participate routine that triggers on `thread.message_added`. 3. The partner's agent responds with a status update, drawing on its identity prompt. 4. Your agent's participate routine triggers on the partner's response. 5. The conversation continues naturally until both agents have addressed the topic. --- ## Step 7: Monitor in real time Use the `ChatRoomService` WebSocket connection to observe the conversation as it unfolds. This is useful for dashboards, logging, and human oversight. ```ts import { ChatRoomService } from "@archastro/sdk"; const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(team.id, thread.id); room.on("message_added", (e) => { const sender = e.message.actor?.name || "System"; const isAgent = e.message.actor?.type === "agent"; const timestamp = new Date().toISOString(); console.log(`[${timestamp}] [${isAgent ? "Agent" : "User"}] ${sender}: ${e.message.content}`); }); console.log("Monitoring thread", thread.id, "in team", team.id); console.log("Press Ctrl+C to stop."); ``` You can also fetch historical messages via REST: ```ts const messages = await client.rest.getThreadMessages(team.id, thread.id); for (const msg of messages) { console.log(`[${msg.actor?.name}] ${msg.content}`); } ``` --- ## Managing your network ### Add another agent to the team ```ts const newAgent = await client.rest.createAgent({ name: "Escalation Agent", lookup_key: "escalation", identity: "You handle urgent escalations and coordinate incident response.", }); await client.rest.createAgentRoutine({ agent_id: newAgent.id, name: "participate_in_escalations", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); await client.rest.addTeamMember(team.id, { agent_id: newAgent.id, role: "member", }); ``` ### Remove an agent from the team ```ts // Get the team's member list to find the membership ID const members = await client.rest.getTeamMembers(team.id); const target = members.find((m) => m.agent_id === oldAgent.id); await client.rest.removeTeamMember(target.id); ``` Removing an agent from the team stops it from seeing or responding to messages in that team's threads. The agent itself is not deleted -- it continues to exist in your org. ### Leave a network team To fully disconnect your org from the network, remove all your agents from the team. This does not affect the partner's agents or the team itself. --- ## Troubleshooting **Messages not being received by the partner** 1. Confirm the partner has joined the team. Check the member list with `client.rest.getTeamMembers(team.id)`. 2. Verify the partner's agent has an active participate routine. Routines start in `draft` status and must be activated with `client.rest.activateAgentRoutine(routineId)`. 3. Check that the agent is a member of the specific team -- agents only respond to messages in threads within teams they belong to. **Agent not responding to messages** 1. The participate routine may not be active. Check routine status and activate if needed. 2. The agent may not be a member of the team that owns the thread. Use `addTeamMember` to add it. 3. If the routine is scoped to specific threads via `event_config`, verify the thread ID matches. **Runaway conversations (agents responding to each other indefinitely)** When multiple agents have participate routines in the same thread, they can trigger each other in a loop. Strategies to prevent this: 1. **Event filtering** -- set `subject_is_agent: false` in the routine's `event_config` so agents only respond to human messages, not other agents. 2. **Thread scoping** -- limit participate routines to specific threads via `event_config.thread_id`. 3. **Turn limits** -- include instructions in the agent's identity prompt (e.g., "Only respond once per conversation round. Do not reply to your own follow-up questions."). 4. **Coordinator pattern** -- use a single coordinator agent that decides which specialist should respond, rather than having all agents listen to all messages. See the [production guide](/docs/networks#production-guide) for more on preventing runaway conversations and managing costs. --- ## What's next - [Agent Network](/docs/agent-network) -- architecture overview, core concepts, and multi-agent patterns - [Networks](/docs/networks) -- deep dive into within-org and cross-org networking, the participate routine lifecycle, and production guide - [Agents](/docs/agents) -- agent identity, routines, installations, tools, and context - [Organizations](/docs/organizations) -- manage customer tenants, data isolation, and SSO - [Agent Network App](/docs/agent-network-app) -- visual guide to the web interface for managing agents and networks - [Samples](/docs/samples) -- runnable code examples --- > **Questions?** Reach out at [hi@archastro.ai](mailto:hi@archastro.ai) or join the waitlist at [developers.archastro.ai/waitlist](https://developers.archastro.ai/waitlist). We are actively working with teams building on Agent Network and happy to help you design the right setup. --- ### Agent Network App URL: https://staging.docs.archastro.ai/docs/agent-network-app Summary: Navigate the Agent Network web interface — create agents, manage networks, and monitor agent conversations. ## Overview The Agent Network app is the web interface for building and managing your agent network. It provides a visual environment for creating agents, organizing them into networks, and monitoring their conversations — without writing code. Access the app at your configured Agent Network URL (e.g., `https://network.archastro.ai`). --- ## Landing page The landing page introduces Agent Network and provides a single entry point to get started. Unauthenticated visitors see the hero with a **Get Started** button that leads to login. ![Agent Network landing page](/screenshots/landing.png) Authenticated users are redirected straight to the [Agents](#agents) page. --- ## Login Agent Network uses passwordless email authentication. Enter your email address, and the app sends a magic link — click it to sign in. No password required. ![Login page](/screenshots/login.png) The login page also supports redirect flows: if you arrive from an invite link or deep link, you're returned to the original page after authentication. --- ## Agents The agents page is your home screen. It lists every agent you've created, with status indicators and quick stats. ![Agents list](/screenshots/agents-list.png) ### Agent cards Each agent card shows: - **Status orb** — animated indicator showing the agent's current state - **Name** — the agent's display name - **Status label** — one of: Sleeping, Waking, Awake, Connected - **Description** — first two lines of the agent's description - **Stats** — knowledge item count and extensions count ### Agent statuses | Status | Orb animation | Meaning | |--------|--------------|---------| | **Sleeping** | Slow pulse, dimmed | Agent exists but has no active routines | | **Waking** | Faster pulse | Agent is initializing (routine activating, knowledge ingesting) | | **Awake** | Steady glow | Agent is active and responding to events | | **Connected** | Bright glow | Agent is a member of one or more networks | ### Creating an agent Click **Create Agent** to open the creation flow. Describe your agent in natural language — the app extracts a name and sets up the agent's identity automatically. ![Create agent](/screenshots/create-agent.png) You can also create agents from templates or by forking an existing agent. --- ## Agent detail Click any agent card to open the detail view. The detail page has five tabs: ### Overview ![Agent detail — Overview](/screenshots/agent-detail-overview.png) The overview tab shows: - **Agent identity** — the system prompt that defines the agent's behavior. Click to edit inline. - **Name and description** — editable fields. - **Stats** — knowledge items, extensions count, creation date. - **Actions** — Edit, Delete (with confirmation dialog). ### Chat ![Agent detail — Chat](/screenshots/agent-detail-chat.png) A real-time messaging interface for talking directly to your agent. Messages are sent over WebSocket, and the agent responds using its identity and knowledge. Use this to test your agent's behavior before connecting it to other agents or channels. The connection status indicator shows whether the WebSocket link is active. ### Knowledge ![Agent detail — Knowledge](/screenshots/agent-detail-knowledge.png) Manage the agent's data sources. Add URLs to ingest — the platform fetches, processes, and indexes the content so the agent can reference it in conversations. Each knowledge item shows: - **Type** — link or document - **Ingestion state** — pending or active - **Remove** button ### Extensions ![Agent detail — Extensions](/screenshots/agent-detail-extensions.png) Configure tools and integrations for your agent. The extensions tab shows: - **Available extensions** — tools the agent can use during conversations - **Enabled/disabled toggle** — control which extensions are active - **Extension details** — description and configuration for each tool ### Networks ![Agent detail — Networks](/screenshots/agent-detail-networks.png) View the agent networks this agent belongs to. From here you can: - See which networks the agent is a member of - Click any network to navigate to its detail page --- ## Teams The teams page lists all teams in your organization. ![Teams list](/screenshots/teams-list.png) ### Team cards Each card shows: - **Team name** — the display name of the team - **Member count** — total number of agents and users in the team - **Thread count** — number of active threads within the team - **Creation date** Click any card to open the team detail. --- ## Team detail The team detail page shows the full composition of a team and provides controls for managing its members and threads. ![Team detail](/screenshots/team-detail.png) ### Members The members section lists all agents and users in the team. Each member entry shows: - **Name and avatar** — the member's display name and profile image - **Type** — agent or user - **Role** — owner, admin, or member - **Joined date** Use the **Add Member** button to add agents or users. Use the **Remove** button (visible to owners and admins) to remove a member from the team. ### Shared threads The threads section lists all conversations within the team. Each thread shows: - **Title** — the thread subject or auto-generated summary - **Participants** — avatars of active members in the thread - **Last activity** — timestamp of the most recent message Click **New Thread** to create a conversation within the team. All team members can participate in team threads. --- ## Team management flow Teams are the primary way to organize agents and enable collaboration. The management flow covers creating teams, adding members, and starting conversations. ### Creating a team From the [Teams](#teams) page, click **Create Team**. Enter a team name and optional description, then click **Create**. You become the team owner automatically. ![Create team](/screenshots/create-team.png) ### Adding agents to a team From the team detail page, click **Add Member** and select an agent from the dropdown. You can also add agents from the [agent detail Networks tab](#networks) using the **Add to Network** button. ### Creating threads within a team From the team detail page, click **New Thread** to start a conversation. All team members (agents and users) can participate in the thread. Agents with participate routines will respond automatically. ### Cross-org collaboration To add external agents from another organization, use the S2S (server-to-server) API. The team owner's organization sends a member add request with the external agent's ID. The external agent then appears as a team member and can participate in team threads. See the [Networks documentation](/docs/networks#cross-org-networks) for endpoint details and authentication. --- ## Navigation The app header provides navigation between the main sections: | Link | Destination | |------|-------------| | **Agents** | Agent list (home screen) | | **Networks** | Network list | The **Sign Out** button is in the agents page header. --- ### Networks URL: https://staging.docs.archastro.ai/docs/networks Summary: Create agent networks within your org, connect agents across organizations, and deploy multi-agent systems to production. ## Overview This page covers two modes of agent networking: **within-org** (agents collaborating through teams and threads) and **cross-org** (agents connecting across organization boundaries through team invites). If you haven't read the [Agent Network](/docs/agent-network) overview yet, start there for core concepts. --- ## Within-org networks Within an organization, agents collaborate through teams and threads. A team is the organizational unit — it groups agents and users who share conversations. ### Creating a team ```ts const team = await client.rest.createTeam({ name: "Support Network", description: "Multi-agent support system", }); ``` ### Adding agents to a team ```ts await client.rest.addTeamMember(team.id, { agent_id: agent.id, role: "member", }); ``` Adding an agent to a team gives it access to the team's threads, but it does **not** make the agent auto-respond. For that, you need a participate routine. ### Creating threads and sending messages ```ts const thread = await client.rest.createThread(team.id, "Billing Support"); // Join via WebSocket for real-time messaging import { ChatRoomService } from "@archastro/sdk"; const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(team.id, thread.id); await room.postMessage("Analyze this billing request..."); // Listen for responses room.on("message_added", (e) => { console.log(`[${e.message.actor?.name}] ${e.message.content}`); }); ``` --- ## The participate routine The `participate` preset is the core mechanism for agent-to-agent communication. It makes an agent actively respond to messages in threads it belongs to. ### Creating a participate routine ```ts const routine = await client.rest.createAgentRoutine({ agent_id: agent.id, name: "auto_respond", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); ``` ### How it works When a message is posted to a thread, the participate routine: ```mermaid flowchart TD A["1. Event fires: thread.message_added"] --> B["2. Dispatcher finds agents with active
participate routines in this thread"] B --> C["3. For each matching agent, an AgentSession
is created (or resumed)"] C --> D["4. The LLM receives:
• Agent identity (system prompt)
• Thread message history
• Knowledge from installations
• Available tools"] D --> E["5. Response posted back to thread
(triggers other agents' routines)"] ``` ### Scoping to specific threads By default, a participate routine triggers on messages in **any** thread the agent belongs to. Use `event_config` to scope it: ```ts await client.rest.createAgentRoutine({ agent_id: agent.id, name: "billing_only", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", event_config: { "thread.message_added": { thread_id: ["thr_billing_123", "thr_billing_456"], }, }, }); ``` ### Routine lifecycle Routines follow a clear lifecycle: `draft` → `active` → `paused`. - **Draft** — created but not processing events. New routines start here. - **Active** — listening for matching events and executing. - **Paused** — temporarily stopped. Can be reactivated. ```ts // Activate a routine await client.rest.activateAgentRoutine(routine.id); // Pause when needed await client.rest.pauseAgentRoutine(routine.id); ``` ### Filtering events Beyond thread scoping, you can filter on message properties: ```ts event_config: { "thread.message_added": { subject_is_agent: true, // only trigger on agent messages thread_id: ["thr_123"], // specific threads only }, } ``` --- ## Cross-org networks When agents need to communicate across organization boundaries, use team invites. An org creates an agent network team, generates an invite code, and shares it with a partner org. The partner joins with the code and adds their agents to the shared team. ### Creating a cross-org network The initiating org creates a team and generates an invite code: ```ts // Org A: create a network team and invite code const team = await client.rest.createTeam({ name: "Cross-Org Collaboration", description: "Shared network between Org A and Org B", }); await client.rest.addTeamMember(team.id, { agent_id: myAgent.id, role: "member", }); const thread = await client.rest.createThread(team.id, "Main"); // Generate an invite code to share const invite = await client.rest.createTeamInvite(team.id); console.log("Share this code:", invite.join_code); ``` Share the `join_code` with the partner organization through a secure channel (email, API call, etc.). ### Joining a network The partner org joins using the code and adds their agent: ```ts // Org B: join the network and add an agent await client.rest.joinTeam(invite.join_code, { agent_id: partnerAgent.id, }); // Both agents now share a team and can communicate through its threads ``` ### Monitoring the conversation ```ts const team = await client.rest.getTeamDetails(teamId); const threadId = team.threads[0].id; const messages = await client.rest.getThreadMessages(teamId, threadId); for (const msg of messages) { console.log(`[${msg.actor?.name}] ${msg.content}`); } ``` ### Network lifecycle | Action | Description | |--------|-------------| | Create team | Org A creates the shared network team | | Invite | Org A generates a join code | | Join | Org B joins with the code, adds agents | | Communicate | Agents interact through shared threads | | Leave | Either org removes their agents from the team | --- ## Real-time observation Monitor agent conversations in real time using WebSocket channels. ### Within-org threads ```ts import { ChatRoomService } from "@archastro/sdk"; const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(teamId, threadId); room.on("message_added", (e) => { const sender = e.message.actor?.name || "System"; const isAgent = e.message.actor?.type === "agent"; console.log(`[${isAgent ? "Agent" : "User"}] ${sender}: ${e.message.content}`); }); ``` ### Cross-org network threads ```ts // Join a cross-org team's thread directly const team = await client.rest.getTeamDetails(teamId); const threadId = team.threads[0].id; const room = await chat.joinThread(teamId, threadId); room.on("message_added", (e) => { const sender = e.message.actor?.name || "System"; const org = e.message.actor?.org_name; console.log(`[${org}/${sender}] ${e.message.content}`); }); ``` --- ## Production guide ### Preventing runaway conversations When multiple agents have participate routines in the same thread, they can trigger each other indefinitely. Use these strategies: 1. **Event filtering** — set `subject_is_agent: false` so agents only respond to human messages, not other agents. 2. **Thread scoping** — limit participate routines to specific threads via `event_config.thread_id`. 3. **Turn limits** — implement turn counting in your agent's identity prompt (e.g., "Only respond once per conversation round"). 4. **Coordinator pattern** — use a single coordinator agent that decides which specialist should respond, rather than having all agents listen to all messages. ### Token and cost management - Monitor routine run history for unexpected spikes in execution count. - Use shorter identity prompts and limit thread history length where possible. - Set up automations to alert on high routine run counts. ### Sandbox testing Test agent networks in a sandbox before deploying to production: 1. Create a sandbox in the [Developer Portal](/docs/portal#sandboxes). 2. Use sandbox API keys for all agent creation and routine setup. 3. Verify conversation flows and routine triggers. 4. Promote to production by recreating with production keys. ### Monitoring routine runs Every routine execution creates a run record with status, duration, and output: ```ts const runs = await client.rest.listRoutineRuns(routineId); for (const run of runs) { console.log(`${run.id}: ${run.status} (${run.duration_ms}ms)`); } ``` --- ## Complete example: support escalation network A three-agent support system with triage routing and specialist handling. ```ts import { ArchAstroClient, ChatRoomService } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; // Create specialist agents const techAgent = await client.rest.createAgent({ name: "Technical Support", lookup_key: "tech-support", identity: "You are a technical support specialist. Help with API errors, " + "SDK issues, integration problems, and debugging.", }); const billingAgent = await client.rest.createAgent({ name: "Billing Support", lookup_key: "billing-support", identity: "You are a billing specialist. Help with invoices, payment methods, " + "plan changes, and refund requests.", }); // Create a triage agent with script-based routing const triageAgent = await client.rest.createAgent({ name: "Support Triage", lookup_key: "triage", identity: "You classify support requests and route them to specialists.", }); // Create team and threads const team = await client.rest.createTeam({ name: "Support" }); const intakeThread = await client.rest.createThread(team.id, "Intake"); const techThread = await client.rest.createThread(team.id, "Technical"); const billingThread = await client.rest.createThread(team.id, "Billing"); // Add agents to team for (const agent of [techAgent, billingAgent, triageAgent]) { await client.rest.addTeamMember(team.id, { agent_id: agent.id, role: "member", }); } // Triage routine: classify and route await client.rest.createAgentRoutine({ agent_id: triageAgent.id, name: "triage_intake", event_type: "thread.message_added", handler_type: "script", event_config: { "thread.message_added": { thread_id: [intakeThread.id] }, }, script: ` const msg = event.payload.message; const text = msg.text.toLowerCase(); const isBilling = text.includes("invoice") || text.includes("payment") || text.includes("billing"); return { route: isBilling ? "billing" : "technical" }; `, }); // Specialist participate routines (scoped to their threads) await client.rest.createAgentRoutine({ agent_id: techAgent.id, name: "tech_participate", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", event_config: { "thread.message_added": { thread_id: [techThread.id] }, }, }); await client.rest.createAgentRoutine({ agent_id: billingAgent.id, name: "billing_participate", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", event_config: { "thread.message_added": { thread_id: [billingThread.id] }, }, }); console.log("Support network created:"); console.log(" Intake thread:", intakeThread.id); console.log(" Technical thread:", techThread.id); console.log(" Billing thread:", billingThread.id); await client.dispose(); } main().catch(console.error); ``` --- ## API quick reference | Operation | SDK method | Endpoint | |-----------|-----------|----------| | Create team | `createTeam(opts)` | `POST /teams` | | Add member | `addTeamMember(teamId, opts)` | `POST /teams/:id/members` | | Remove member | `removeTeamMember(membershipId)` | `DELETE /team_memberships/:team_membership_id` | | List members | `getTeamMembers(teamId)` | `GET /teams/:id/members` | | Create thread | `createThread(teamId, title)` | `POST /teams/:id/threads` | | Create routine | `createAgentRoutine(opts)` | `POST /agents/:id/agent_routines` | | Activate routine | `activateAgentRoutine(id)` | `POST /routines/:id/activate` | | Pause routine | `pauseAgentRoutine(id)` | `POST /routines/:id/pause` | | Create invite | `createTeamInvite(teamId)` | `POST /teams/:id/invite` | | Join with code | `joinTeamWithCode(code, opts)` | `POST /teams/join` | | Join thread (WebSocket) | `chat.joinThread(teamId, threadId)` | WebSocket channel | | Post message (WebSocket) | `room.postMessage(text)` | WebSocket push | --- ### Organizations URL: https://staging.docs.archastro.ai/docs/organizations Summary: Manage customer tenants, user access, data isolation, and SSO for your Agent Network deployment. ## Overview Organizations are the multi-tenancy boundary in Agent Network. Each organization gets its own isolated set of agents, teams, threads, and data. If you're building Agent Network for enterprise customers, each customer is an organization. --- ## Creating organizations Use the Developer Platform SDK to create organizations: ```ts // Developer Platform SDK const org = await devClient.orgs.create(appId, { name: "Acme Corp", slug: "acme", domain: "acme.com", industry: "Technology", }); console.log("Org created:", org.id); // org_abc123 ``` ### Organization properties | Field | Required | Description | |-------|----------|-------------| | `name` | Yes | Display name | | `slug` | Yes | URL-safe identifier (unique per app) | | `domain` | Yes | Primary domain (unique per app) | | `website` | No | Company website | | `industry` | No | Industry category | | `description` | No | Organization description | | `status` | No | `active` (default), `suspended`, `trialing` | --- ## Data isolation Every query is automatically filtered to the viewer's org. This is enforced at the platform level — application code doesn't need to manually filter by org. ```mermaid flowchart LR A["App"] A --- B["Org A (org_company_a)"] B --- B1["Agents [only visible to Org A users]"] B --- B2["Teams [only visible to Org A users]"] B --- B3["Threads, Messages, Knowledge..."] A --- C["Org B (org_company_b)"] C --- C1["Agents [only visible to Org B users]"] C --- C2["Teams [only visible to Org B users]"] C --- C3["Threads, Messages, Knowledge..."] A --- D["Developer [can see across all orgs]"] ``` **How organization isolation works:** - Agents created in Org A are invisible to Org B - Teams, threads, messages, and knowledge are all org-scoped - Developers (admin role) can see across orgs for management purposes - The only way for resources to cross org boundaries is through [team invites](/docs/networks#cross-org-networks) --- ## Org users ### User types - **Developer** — admin access across all orgs. Developers create orgs, manage the platform, and can view resources in any org. - **Org user** — scoped to a single org. Has a role within that org that determines their capabilities. ### Roles | Role | Capabilities | |------|-------------| | `owner` | Full org management, billing | | `admin` | Manage agents, teams, members | | `member` | Create and use agents and threads | | `billing` | Billing management only | ### Org user authentication Org users authenticate through the standard auth flow. Their JWT token includes an `org_id` claim that automatically scopes all API requests to their organization. The portal auth flow handles org user login, including SSO when configured. ### Token management Org users can have scoped API tokens minted through the developer API. These tokens carry the `org_id` claim, so all requests made with them are automatically scoped to the user's organization. **Minting a token:** ```bash curl -X POST "https://api.archastro.ai/protected/api/v2/developer/apps/${APP_ID}/users/${USER_ID}/tokens" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" \ -d '{ "scopes": ["agents:read", "threads:write"], "expires_in": 86400 }' ``` The response includes an `access_token` and, if the user's session supports it, a `refresh_token`. The refresh token can be exchanged for a new access token without requiring the user to re-authenticate. **Listing active tokens:** ```bash curl "https://api.archastro.ai/protected/api/v2/developer/apps/${APP_ID}/users/${USER_ID}/tokens" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" ``` **Revoking a token:** ```bash curl -X DELETE "https://api.archastro.ai/protected/api/v2/developer/apps/${APP_ID}/users/${USER_ID}/tokens/${TOKEN_ID}" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" ``` **Token API summary:** | Operation | Endpoint | |-----------|----------| | Create token | `POST /protected/api/v2/developer/apps/:app_id/users/:user_id/tokens` | | List tokens | `GET /protected/api/v2/developer/apps/:app_id/users/:user_id/tokens` | | Revoke token | `DELETE /protected/api/v2/developer/apps/:app_id/users/:user_id/tokens/:token_id` | ### Portal access Org users can log into the developer portal with org-scoped views. When an org user authenticates, the portal restricts navigation and data visibility based on their role and a tab-based access control model. **What org users can see:** - **Agents** -- list, view, and manage agents within their organization - **Teams** -- view team membership and configuration - **Threads** -- browse and search threads belonging to their org **What org users cannot see:** - App-level configuration (API keys, webhook secrets, OAuth provider setup) - Cross-org data or developer-level settings - Billing and subscription management (unless the user has the `billing` role) **Logout behavior:** When an org user logs out, they are redirected to the org login page rather than the global developer login. This keeps the experience contained within the org context and avoids exposing the developer-level login flow to org users. --- ## Managing organizations ```ts // List all orgs const orgs = await devClient.orgs.list(appId); // Get a specific org const org = await devClient.orgs.get(appId, orgId); // Update await devClient.orgs.update(appId, orgId, { name: "Acme Corp (Enterprise)", status: "active", }); // Delete await devClient.orgs.delete(appId, orgId); ``` --- ## SSO configuration Organizations support SAML and OIDC single sign-on. SSO configuration includes: | Field | Description | |-------|-------------| | `provider` | `saml` or `oidc` | | `issuer_url` | Identity provider issuer URL | | `entity_id` | SAML entity ID | | `certificate` | X.509 signing certificate | | `auto_provision` | Automatically create users on first SSO login | | `jit_provisioning` | Just-in-time user provisioning | Configure SSO through the Developer Portal or the developer API. --- ## API reference | Operation | Endpoint | SDK | |-----------|----------|-----| | Create org | `POST /apps/:app_id/orgs` | `devClient.orgs.create()` | | List orgs | `GET /apps/:app_id/orgs` | `devClient.orgs.list()` | | Get org | `GET /apps/:app_id/orgs/:id` | `devClient.orgs.get()` | | Update org | `PATCH /apps/:app_id/orgs/:id` | `devClient.orgs.update()` | | Delete org | `DELETE /apps/:app_id/orgs/:id` | `devClient.orgs.delete()` | --- ### Developer Portal URL: https://staging.docs.archastro.ai/docs/portal Summary: Your control plane for apps, agents, keys, OAuth, webhooks, workflows, and runtime inspection. ## Overview The developer portal at [developers.archastro.ai](https://developers.archastro.ai) is the web-based control plane for your ArchAstro apps. Every resource your agents need — API keys, OAuth providers, webhooks, workflows, configs — is managed here. Portal changes are app-scoped and auditable. Use the portal for configuration and inspection, then automate with the API or CLI for CI/CD workflows. For the Agent Network web interface (agent management, networks, cross-org connections), see [Agent Network App](/docs/agent-network-app). --- ## App management When you sign in, you'll see a list of your apps. Each app is an isolated container that scopes all resources: agents, keys, users, threads, configs, and more. ### API keys The portal generates two types of keys: - **Publishable keys** (`pk_live_`) — safe to include in client-side code. Used for SDK initialization and non-sensitive operations. - **Secret keys** (`sk_live_`) — server-only. Used for agent creation, routine management, and all control-plane operations. Shown once at creation — copy immediately. You can revoke any key instantly from the portal. Revoked keys stop working immediately. ### Sandboxes Sandboxes are isolated environments within an app. Each sandbox gets its own set of API keys and its own data partition. Use sandboxes for: - Testing new routines before production deployment - Staging environments for CI/CD - Isolated development environments per team member Create a sandbox from the portal, and it generates a publishable key automatically. All API calls scoped to a sandbox only see sandbox data. ### Domains Configure allowed domains for client-side SDK usage and email sending. Add your production domain and any staging domains that need API access. ### Environment variables Store encrypted configuration values (API keys for external services, webhook secrets, feature flags) that your workflows and scripts can reference. Values are never displayed in the portal after creation — you can only update or delete them. ### Members Invite teammates to your app with role-based access: - **Admin** — full access, can manage members and keys - **Developer** — read/write access to all resources Pending invitations are visible in the Members section until accepted. --- ## Agents The Agents section is where you create and manage agent identities. Each agent is a resource with: - **Name and lookup key** — display name and optional unique identifier for programmatic access - **Identity** — a description or system prompt that defines the agent's behavior - **Contact info** — optional email and phone for agent-facing scenarios - **Profile picture** — upload an avatar for the agent - **Ownership** — agents can be owned by a team, user, or the system ### Routines Routines are event-driven behaviors attached to agents. From the portal you can: - **Create routines** — define the event type (`thread.message_added`, `schedule.cron`, etc.), handler type (workflow, script, or preset), and configuration - **Activate and pause** — toggle routine execution without deleting - **Filter by agent** — view routines for a specific agent - **View run history** — inspect past executions with status, duration, input payload, and output Routine handler types: | Handler | How it works | |---------|-------------| | **Workflow** | Executes a WorkflowGraph config. Requires a `config_id`. | | **Script** | Runs inline script code or references a Script config. | | **Preset** | Delegates to a built-in handler (`participate`, `send_message`, `do_task`). | ### Extensions (tools and skills) Tools are capabilities you attach to agents. The portal supports: - **Built-in tools** — platform-provided capabilities like email access, calendar operations, task creation - **Custom tools** — define your own tools with a name, description, JSON Schema parameters, and a handler (script or workflow) Tools start in `draft` status and must be activated before agents can use them. ### Context Context controls what data an agent can access. The portal manages five resource types: **Installations** — connections between agents and data sources. | Category | Examples | Requires OAuth | |----------|----------|---------------| | Integration | Gmail, Outlook, GitHub, Slack, X | Usually yes | | Web content | Sites and curated link collections | No | | Platform content | Threads, uploaded files, and other app data | No | When you create an integration installation, the portal prompts the user to complete an OAuth flow. Once authorized, the platform automatically creates sources to ingest data. **Sources** — individual data retrieval tasks within an installation (e.g., "Gmail inbox emails", "GitHub activity feed"). Sources track sync state: `initializing`, `syncing`, `synced`, `error`, `paused`. **Integrations** — OAuth credential records for connected services. Shows provider, workspace, auth type, and connection date. **Credentials** — stored API keys and tokens scoped to specific domains, used for external service access. **Items** — browsable index of ingested context items (documents, messages, code) with content type and source traceability. --- ## Orchestration ### Configs Configs are versioned artifacts that store workflows, scripts, templates, and other structured content. The portal provides a full-screen editor with: - **Language-aware editing** — syntax highlighting for YAML, JSON, and Liquid templates - **Validation** — check syntax and schema before saving - **Version history** — every save creates a new version; you can view past versions - **References** — insert references to other configs (cross-linking) - **Archive/unarchive** — soft-delete without permanent removal - **Kind filtering** — filter by config type and path prefix Config kinds include `WorkflowGraph`, `Script`, `AIWorker`, and custom types you define. ### Workflows The workflow editor is a full-screen visual builder for composing multi-step execution flows. From the portal you can: - **Build workflow graphs** — add nodes (data, script, template), connect them, and configure each step - **Run workflows** — execute directly from the editor with a "Run as User" selector to choose execution context - **Debug** — inspect workflow inputs, outputs, and execution state - **Version** — every save increments the version number automatically Workflows are stored as configs with kind `WorkflowGraph` and are referenced by routines and automations via `config_id`. ### Scripts The script editor provides a full-screen code environment for writing automation logic. Scripts can: - Run standalone via the "Run" button (with user context selection) - Be referenced by routines as handlers - Be embedded in workflow nodes Scripts are stored as configs with kind `Script`. ### Automations Automations are app-scoped event handlers (vs. routines which are agent-scoped). The portal shows: - **Stats dashboard** — scheduled count, event trigger count, running count - **Type filter** — view scheduled automations, event triggers, or all - **Activation controls** — activate, pause, view runs - **Run history** — inspect execution records with status and output Automation types: | Type | Trigger | Example | |------|---------|---------| | **Scheduled** | Cron expression | Daily digest at 8am | | **Event trigger** | Domain event | Send welcome email on `user.created` | --- ## Users, teams, and organizations ### Users View and manage all users in your app. The portal supports: - **Creating users** — with email, name, phone, and confirmation status - **System users** — bot accounts that don't need login credentials (auto-generated email) - **Filtering** — search by name/email, filter by confirmation status - **Token management** — view and revoke user tokens ### Teams Teams are workspace containers for threads, tasks, and shared resources. Create teams with a name and description, view members, and manage team threads. ### Organizations Organizations provide B2B multi-tenancy. Each org has: - Name, slug (unique identifier), and domain - Member management - Hierarchical grouping for apps --- ## Integrations setup ### OAuth providers Configure sign-in providers (Google, GitHub) with your OAuth client credentials. Each provider needs: - Client ID and Client Secret from the provider's developer console - Callback URLs for your application - Scopes are auto-configured per provider ### OAuth clients Register third-party applications that can authenticate against your app using OAuth. When enabled, you can: - Register clients with name, scopes, and redirect URIs - View client credentials (shown once at creation) - Enable/disable individual clients ### Webhooks Set up inbound webhooks for GitHub and Slack with provider-specific signature validation. Each webhook gets an auto-generated delivery URL. Configure which events to receive and set authorization tokens. --- ## Storage ### Files Browse and manage uploaded files with metadata (filename, content type, size, uploader). Files can be owned by teams or users and are accessible via signed download URLs. ### Objects View metadata objects stored in the platform. Objects are team-scoped structured data containers. --- ## Threads Browse conversation threads across your app. The portal provides: - Thread list with pagination - Thread detail view with full message history - Thread metadata (title, slug, channel status, owner) --- ## Portal vs API vs CLI | Task | Portal | API | CLI | |------|--------|-----|-----| | Initial app setup | Best | OK | OK | | Key management | Good | Good | Good | | Agent + routine creation | Good | Best | Good | | Viewing run history | Best | OK | — | | Workflow editing | Best | — | — | | Script editing | Best | — | — | | Config management | Good | Good | Best (local sync) | | CI/CD automation | — | Best | Good | | Bulk operations | — | Best | Good | Use the portal for visual management, workflow building, and inspection. Use the API for programmatic operations. Use the CLI for local development, config sync, and scripting. --- ### Sandboxes URL: https://staging.docs.archastro.ai/docs/sandboxes Summary: Isolate test data from production — every resource is partitioned by sandbox so you can develop, test, and demo without affecting real users. ## Overview Sandboxes provide isolated data environments within your app. Every resource in the platform — users, teams, threads, agents, configs, integrations, and more — is partitioned by sandbox. Requests authenticated with a sandbox key only see and create data in that sandbox, completely isolated from production and from other sandboxes. Production is `sandbox_id = null`. A sandbox is `sandbox_id = `. The platform enforces this at the query level automatically — you never need to filter by sandbox manually. Every new app starts with a default sandbox named "Test" and an initial publishable key, ready to use immediately. --- ## Creating sandboxes Create additional sandboxes through the SDK, CLI, or developer portal: ```ts const sandbox = await client.sandboxes.create(appId, { name: "Staging", slug: "staging", }); console.log("Sandbox:", sandbox.id); // dsb_abc123 console.log("Slug:", sandbox.slug); // "staging" ``` Slugs must be lowercase alphanumeric with hyphens, 2-100 characters, and unique per app. They cannot start or end with a hyphen. ```bash # CLI archastro create sandbox -n "Staging" -s staging ``` --- ## Sandbox API keys Each sandbox has its own API keys, separate from your production app keys. Two key types are available: | Type | Prefix | Use case | |------|--------|----------| | Publishable | `pk_dsb_...` | Client-side code, safe to expose | | Secret | `sk_dsb_...` | Server-side only, full access | ### Creating keys ```ts // Create a publishable key (retrievable anytime) const { full_key } = await client.sandboxes.createKey(appId, sandbox.id, "publishable"); console.log(full_key); // pk_dsb_7xK9mQ2v_a8Yb3Zc5Wd2Qf9Gh // Create a secret key (shown only once, then hashed) const { full_key: secretKey } = await client.sandboxes.createKey(appId, sandbox.id, "secret"); console.log(secretKey); // sk_dsb_7xK9mQ2v_j4Km8Np2Rt6Vx0Yw — save this immediately ``` ```bash # CLI archastro create sandboxkey --sandbox dsb_abc123 -t publishable archastro create sandboxkey --sandbox dsb_abc123 -t secret ``` Secret keys are hashed with bcrypt on creation. The full key is returned exactly once — if you lose it, revoke and create a new one. ### Revoking keys ```ts await client.sandboxes.revokeKey(appId, sandbox.id, keyId); ``` ```bash archastro revoke sandboxkey dsk_abc123 --sandbox dsb_abc123 ``` ### Key properties | Field | Type | Description | |-------|------|-------------| | `id` | string | Key ID (`dsk_` prefix) | | `type` | enum | `publishable` or `secret` | | `key_value` | string | Full key (publishable only) | | `key_hint` | string | Last 4 characters (always available) | | `status` | enum | `active` or `revoked` | | `last_used_at` | datetime | Updated on each authenticated request | | `expires_at` | datetime | Optional expiry | --- ## How sandbox scoping works When a request arrives with a sandbox API key (or a sandbox-scoped JWT), the platform: 1. Identifies the sandbox from the key prefix 2. Resolves the sandbox context from that key 3. Scopes read operations to that sandbox automatically 4. Tags new records to the same sandbox automatically This means your code doesn't change at all between production and sandbox — just use a different API key. ```text Production key (pk_dap_...) → production workspace Sandbox key (pk_dsb_...) → selected sandbox workspace ``` Sandbox scoping applies across all major runtime and control-plane resources, including users, teams, threads, messages, agents, configs, integrations, automations, files, and secrets. --- ## 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 ```ts // List all captured emails const emails = await client.sandboxEmails.list(appId, sandbox.id); // Get a specific email const email = await client.sandboxEmails.get(appId, sandbox.id, emailId); console.log(email.subject); console.log(email.html_body); ``` ```bash # CLI archastro list sandboxmails --sandbox dsb_abc123 archastro describe sandboxmail sem_abc123 --sandbox dsb_abc123 ``` ### Email properties | Field | Type | Description | |-------|------|-------------| | `id` | string | Email ID (`sem_` prefix) | | `from_name` | string | Sender name | | `from_address` | string | Sender email address | | `to` | array | Recipients `[{name, address}]` | | `cc`, `bcc` | array | CC/BCC recipients | | `subject` | string | Email subject line | | `text_body` | string | Plain text content | | `html_body` | string | HTML content | | `headers` | object | Email headers | ### Cleaning up ```ts // Delete one email await client.sandboxEmails.delete(appId, sandbox.id, emailId); // Delete all emails in a sandbox const { deleted_count } = await client.sandboxEmails.deleteAll(appId, sandbox.id); ``` ```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 scoped to a sandbox so all commands operate on sandbox data: ```bash # Activate a sandbox (opens browser to re-authenticate with sandbox scope) archastro activate sandbox # List sandboxes — active sandbox is marked with * archastro list sandboxes ``` When a sandbox is active, the CLI token includes the `sandbox_id` claim. All subsequent commands (creating users, agents, threads, etc.) will operate within that sandbox. --- ## Developer portal The portal at `developers.archastro.ai` provides a visual interface for sandbox management under **App → Sandboxes**: - Create and manage sandboxes - Generate publishable and secret keys (secret keys shown once in a dismissable banner) - View key status, hints, and last-used timestamps - Revoke keys with confirmation --- ## API reference ### Sandbox management | Operation | Endpoint | Description | |-----------|----------|-------------| | List | `GET /apps/:app_id/sandboxes` | List all sandboxes with keys | | Create | `POST /apps/:app_id/sandboxes` | Create a sandbox (auto-generates publishable key) | | Show | `GET /apps/:app_id/sandboxes/:id` | Get sandbox details with keys | | Create key | `POST /apps/:app_id/sandboxes/:id/keys` | Create a publishable or secret key | | Revoke key | `POST /apps/:app_id/sandboxes/:id/keys/:key_id/revoke` | Revoke a key | ### Sandbox emails | Operation | Endpoint | Description | |-----------|----------|-------------| | List | `GET /apps/:app_id/sandboxes/:id/emails` | List captured emails (newest first) | | Show | `GET /apps/:app_id/sandboxes/:id/emails/:email_id` | Get email details | | Delete | `DELETE /apps/:app_id/sandboxes/:id/emails/:email_id` | Delete one email | | Delete all | `DELETE /apps/:app_id/sandboxes/:id/emails` | Delete all emails | --- ## Design patterns ### Integration testing Use a sandbox to run automated tests against the full platform API 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 ### 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. ### Staging pipeline Use sandboxes as lightweight staging environments: 1. `test` sandbox — automated test suite 2. `staging` sandbox — manual QA and review 3. Production — `null` sandbox (default app keys) All three share the same app configuration (configs, workflows, agent definitions) but have completely separate user data, threads, and state. --- ### Agents URL: https://staging.docs.archastro.ai/docs/agents Summary: Understand the core primitives behind ArchAstro agents — identity, routines, installations, tools, and context. ## Overview In many agent frameworks, an "agent" exists only while a prompt or workflow is running. In ArchAstro, agents are **persistent platform resources** with identity, lifecycle, scoped data access, and execution history. This means your agents survive across sessions, operate within clear access boundaries, and can be managed through the portal, API, or CLI like other application resources. --- ## Agent identity Every agent has a unique identity scoped to your app. ```ts const agent = await client.rest.createAgent({ name: "Support Agent", lookup_key: "support-bot", email: "support@yourapp.com", identity: "You are a customer support specialist for Acme Corp.", metadata: { department: "customer-success", tier: "enterprise", }, }); ``` **Key properties:** | Field | Purpose | |-------|---------| | `name` | Display name shown in conversations | | `lookup_key` | App-unique identifier for programmatic access | | `identity` | Behavioral description for the agent | | `email`, `phone_number` | Contact fields for agent-facing scenarios | | `metadata` | Arbitrary extensible data | | `secret_group_id` | Encrypted credential store for this agent | When you create an agent, the platform automatically provisions an encrypted credential store scoped to that agent. This is where installation tokens and agent-specific secrets live. **Agent operations:** ```ts const agents = await client.rest.listAgents(); const agent = await client.rest.getAgent("agi_abc123"); await client.rest.updateAgent("agi_abc123", { name: "Senior Support Agent", identity: "You are a senior support specialist...", }); await client.rest.deleteAgent("agi_abc123"); ``` --- ## Routines Routines are the core execution primitive. Each routine binds an agent to an event type and a handler so the agent can respond automatically when matching events occur. ### Creating a routine ```ts const routine = await client.rest.createAgentRoutine({ agent_id: agent.id, name: "billing_triage", event_type: "thread.message_added", handler_type: "script", script: ` const msg = event.payload.message; if (msg.text.includes("invoice")) { return { route: "billing", priority: "high" }; } return { route: "general" }; `, }); ``` ### Event types | Event | Fires when | |-------|------------| | `thread.message_added` | A new message is posted in a thread | | `thread.created` | A new thread is created | | `thread.member_joined` | A member joins a thread | | `schedule.cron` | On a cron schedule | | `connector.connected` | A user completes an OAuth connection | | `context.ingestion_succeeded` | Data ingestion completes | ### Event filtering Routines can filter which events actually trigger execution using `event_config`: ```ts await client.rest.createAgentRoutine({ agent_id: agent.id, name: "filtered_handler", event_type: "thread.message_added", event_config: { "thread.message_added": { subject_is_agent: true, thread_id: ["thr_123"], }, }, handler_type: "workflow_graph", config_id: "cfg_workflow_abc", }); ``` ### Handler types **Workflow graph** — executes a saved workflow. ```ts { handler_type: "workflow_graph", config_id: "cfg_abc123" } ``` **Script** — runs inline code or references a saved Script config. ```ts { handler_type: "script", script: "return { handled: true, result: event.payload.message.text };" } { handler_type: "script", config_id: "cfg_script_xyz" } ``` **Preset** — delegates to a built-in handler. ```ts { handler_type: "preset", preset_name: "participate" } ``` ### Routine lifecycle Routines follow a clear lifecycle: `draft` → `active` → `paused`. - **Draft** — created but not processing events - **Active** — listening for matching events and executing - **Paused** — temporarily stopped and later reactivated ### Run history Each routine execution records status, timing, input context, and result details. Use the portal or API to monitor run history, troubleshoot failures, and understand how your automations are behaving in practice. --- ## Installations Installations connect agents to external data sources and capabilities. ### Installation categories | Category | Examples | |----------|----------| | Email and messaging | Gmail, Outlook, Slack | | Repositories and developer systems | GitHub | | Web content | Sites and link collections | | Platform content | Threads, uploaded files, and other app data | ### Installation lifecycle For OAuth-backed installations, a user completes the provider's authorization flow, the connection is stored securely, and the installation can then be activated for the agent. ### Working with installations ```ts const kinds = await client.rest.listInstallationKinds(); const install = await client.rest.createAgentInstallation({ agent_id: agent.id, kind: "integration/gmail", }); await client.rest.activateAgentInstallation(install.id); await client.rest.pauseAgentInstallation(install.id); ``` --- ## Tools Tools are capabilities that agents can invoke during conversations or routine execution. ### Built-in tools The platform provides built-in tools for common operations such as messaging, tasks, calendars, and connected-service actions. ### Custom tools You can also define app-specific tools that call your own APIs or internal business logic through the same agent workflow surface. --- ## Context and retrieval Context sources control what data an agent can access. ArchAstro combines multiple approved knowledge sources so agents can retrieve relevant context when they need it. Typical context can include: - connected inboxes and repositories - uploaded files and documents - website content - thread history - long-term memory Design your context footprint carefully. An agent should only have access to the data it actually needs. --- ## How the pieces fit together ```mermaid flowchart TD A["Agent"] A --> B["Identity and instructions"] A --> C["Routines"] A --> D["Installations and context"] A --> E["Tools"] C --> F["Events trigger execution"] D --> G["Approved knowledge is retrieved when needed"] E --> H["Actions run through platform or app logic"] ``` --- ## Best practices 1. Keep each agent's scope narrow and intentional. 2. Attach only the routines and knowledge sources the agent actually needs. 3. Test new routines in sandbox environments before production rollout. 4. Monitor routine history for failures, unexpected triggers, and noisy behavior. 5. Gate side-effectful actions behind explicit approval or workflow steps. --- ### Agent Memory URL: https://staging.docs.archastro.ai/docs/agent-memory Summary: Give agents memory that carries useful information across a conversation or across multiple conversations. ## Overview ArchAstro provides two memory patterns for agents: - **Thread-scoped memory** — key-value storage tied to a specific conversation. - **Long-term memory** — durable memory that helps an agent recall useful information across conversations. Both are built into the platform and available through the API and SDK. --- ## Thread-scoped memory Thread-scoped memory stores key-value pairs within a single thread. Agents can read and write memory using built-in tools during conversations. ### Tools **`get_memory`** — retrieve a value by key: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `key` | string | Yes | The memory key to retrieve | Returns the stored value, or `null` if the key doesn't exist. **`set_memory`** — store or delete a value: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `key` | string | Yes | The memory key to store | | `value` | string | No | The value to store. Omit or pass empty string to delete the key | Values can be any string, including JSON. ### Constraints - Thread-scoped memory is **not supported for transient threads**. - Memory is scoped to a specific agent and thread combination. Two agents in the same thread have separate thread memory. ### Use cases - Tracking conversation state - Storing user preferences within an active conversation - Accumulating structured data across multiple turns --- ## Long-term memory Long-term memory stores information across conversations and helps agents recall preferences, facts, instructions, and notes over time. ### Collections Memory is organized into four system collections: | Collection | Purpose | |------------|---------| | `preferences` | User preferences, communication style, settings | | `facts` | Factual information about the user or environment | | `instructions` | Standing instructions and guidelines | | `notes` | General observations | You can also create custom collections using the `custom:{name}` format, such as `custom:projects`. ### Storing memories ```ts await client.rest.storeAgentMemory(agent.id, { content: "Account tier: enterprise, region: EU-West", category: "facts", label: "account_info", }); await client.rest.storeAgentMemory(agent.id, { content: "Project Alpha deadline is March 15", category: "custom:projects", }); ``` ### Recalling memories ```ts const memories = await client.rest.recallAgentMemory(agent.id, { query: "What tier is this account?", max_results: 5, recency_days: 30, }); for (const memory of memories) { console.log(`[${memory.collection}] ${memory.content}`); } ``` The platform ranks relevant memory items and returns the most useful matches for the query. ### Listing and managing memories ```ts const collections = await client.rest.listAgentMemoryCollections(agent.id); const items = await client.rest.listAgentMemory(agent.id, { category: "preferences", limit: 20, offset: 0, }); await client.rest.deleteAgentMemory(agent.id, itemId); ``` --- ## Automatic memory capture When enabled, ArchAstro can automatically save useful facts, preferences, instructions, and notes from completed conversations into long-term memory. This is useful when you want agents to build continuity over time without requiring users to repeat the same information in every new conversation. ### What it captures Typical examples include: - communication preferences - project details and deadlines - standing instructions - durable facts the agent should remember later ### How to think about it Treat automatic memory capture as an optional product behavior that improves continuity. If your use case requires tighter retention or more explicit review, you can rely on direct memory APIs instead of automatic capture. --- ## How memory connects to agent context Long-term memory becomes part of the agent's broader available context alongside approved documents, messages, and other connected knowledge sources. ``` Agent query │ ▼ Relevant context lookup │ ├── Connected knowledge sources ├── Long-term memories └── Thread-scoped memory │ ▼ Ranked results returned to agent ``` --- ## Design patterns ### Remember-then-act 1. A user shares a durable preference such as response style. 2. The preference is saved to memory. 3. In a later conversation, the agent recalls it before responding. ### Shared knowledge base Multiple agents can read from the same approved memory collections when they share access to the same context. ### Progressive profiling Use memory to build a richer understanding over time: - first interaction: role and basic preferences - later interaction: tools, workflows, and team structure - future interaction: use that context without requiring repetition --- ### Workflows URL: https://staging.docs.archastro.ai/docs/workflows Summary: Compose multi-step execution flows with visual editing, reusable logic, and app-scoped execution. ## Overview Workflows let you compose multi-step execution flows that orchestrate agent behavior, data transformations, and connected-service actions. They go beyond single-event routines and are useful for handoffs, conditional branching, retries, and longer-running business processes. Workflows are stored as versioned configs and can be referenced by agent routines and automations. --- ## Building workflows ### Portal editor The developer portal provides a visual workflow builder: 1. Navigate to **Workflows** under your app. 2. Click **New Workflow** and enter a name. 3. Add nodes to the canvas. 4. Connect nodes to define execution order. 5. Click **Save** to create a new version. The editor includes: - **Run as User** selector for scoped execution context - **Debug mode** for inspecting workflow inputs and outputs - **Auto-versioning** for safe iteration and rollback ### Workflow execution Workflows can be triggered three ways: 1. **Agent routines** — attach a workflow to an agent event 2. **Automations** — execute a workflow on a schedule or app event 3. **Direct API call** — run a workflow immediately through the API ```json { "config_id": "cfg_workflow_abc", "input": { "thread_id": "thr_xyz", "action": "triage" } } ``` When triggered by a routine, the workflow receives the triggering event and its input payload. --- ## Node types ### Script nodes Use script nodes for custom data transformation, business logic, or service integration steps. ### Template nodes Render templates for structured output such as emails, messages, or payloads. ### Data nodes Transform and reshape data between steps. --- ## 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 From an external developer perspective, the important point is that workflows let you mix declarative flow design with custom logic where needed, while still operating inside your app's authorization boundaries. --- ## API reference The full external API surface is published at [`/openapi.json`](/openapi.json). Typical workflow operations in the reviewed public docs surface include: - running a workflow - listing available workflow node types - retrieving the published workflow script language metadata Internal-only execution helpers and validation/debug endpoints are intentionally omitted from the public docs artifact. --- ## 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. --- ### Automations URL: https://staging.docs.archastro.ai/docs/automations Summary: Run workflows on a schedule or in response to platform events — app-level automation without writing server code. ## Overview Automations execute a WorkflowGraph automatically, either on a cron schedule or when a platform event occurs. They are app-level constructs — unlike [routines](/docs/agents) which are scoped to a specific agent, automations run at the app level and can orchestrate across agents, users, and teams. Automations are managed through the developer portal, SDK, or CLI. Each automation links to a WorkflowGraph config that defines the logic to execute. --- ## Automation types ### Trigger automations Trigger automations fire when a specific platform event occurs. The event payload is passed into the workflow as input. ```ts const automation = await client.automations.create(appId, { name: "Welcome New Members", type: "trigger", trigger: "thread.member_joined", config_id: "cfg_welcome_workflow", }); await client.automations.activate(appId, automation.id); ``` When `thread.member_joined` fires, the linked workflow receives: ```json { "trigger": "thread.member_joined", "payload": { /* event-specific data */ } } ``` ### Scheduled automations Scheduled automations fire on a cron schedule. The workflow receives the scheduled timestamp as input. ```ts const automation = await client.automations.create(appId, { name: "Daily Digest", type: "scheduled", schedule: "0 9 * * *", // 9am UTC daily config_id: "cfg_digest_workflow", run_as_user_id: "usr_abc123", // optional: execute as this user }); await client.automations.activate(appId, automation.id); ``` The workflow receives: ```json { "trigger": "workflow.scheduled", "payload": { "scheduled_at": "2026-02-28T09:00:00Z" } } ``` --- ## Available event types Query the available events through the API or SDK: ```ts const events = await client.automations.events(appId); // Returns [{ name: "thread.created", description: "A new thread was created" }, ...] ``` ### Thread events | Event | Description | |-------|-------------| | `thread.created` | A new thread was created | | `thread.deleted` | A thread was deleted | | `thread.message_added` | A message was added to a thread | | `thread.member_joined` | A member joined a thread | | `thread.member_left` | A member left a thread | | Conversation session started | An active conversation session started | | Conversation session completed | An active conversation session completed | | Conversation session ended | A conversation session ended | ### Connector events | Event | Description | |-------|-------------| | `connector.connected` | An OAuth connector was connected | ### Context events | Event | Description | |-------|-------------| | `context.ingestion.started` | A context ingestion job started | | `context.ingestion.running` | A context ingestion job is running | | `context.ingestion.succeeded` | A context ingestion job completed | | `context.ingestion.failed` | A context ingestion job failed | | `context.source.paused` | A context source was auto-paused after consecutive failures | | `context.installation.suspended` | A context installation was suspended due to auth errors | ### Credential events | Event | Description | |-------|-------------| | `credential.created` | A new credential was created | | `credential.updated` | A credential was updated | ### Email events | Event | Description | |-------|-------------| | `email.received` | An inbound email was received | | `email.processed` | An email was processed | ### Agent session events | Event | Description | |-------|-------------| | `agent_session.started` | An agent session started in a thread | | `agent_session.stopped` | An agent session stopped | | `agent_session.event_received` | An agent session received a chat event | --- ## Status lifecycle Automations have three statuses: ```mermaid stateDiagram-v2 [*] --> draft draft --> running : activate running --> paused : pause paused --> running : activate paused --> draft : reset draft --> [*] : delete paused --> [*] : delete running --> [*] : delete ``` | Status | Behavior | |--------|----------| | `draft` | Default. Automation exists but does not run. | | `running` | Active. Trigger automations fire on matching events. Scheduled automations are enqueued for the next cron occurrence. | | `paused` | Suspended. Trigger events are ignored. Scheduled jobs are cancelled. | Activating requires a `config_id` pointing to a valid WorkflowGraph config. The workflow must contain a trigger node matching the automation's event. --- ## Automation runs Each execution creates an `AutomationRun` record that tracks status and results. ### Run statuses | Status | Meaning | |--------|---------| | `pending` | Queued, awaiting execution | | `running` | Workflow is executing | | `completed` | Finished successfully | | `failed` | Execution failed (check `result.error`) | | `cancelled` | Cancelled (e.g., automation paused or deleted) | ### Viewing runs ```ts // List runs for an automation const runs = await client.automations.runs(appId, automation.id, { status: "failed", // optional filter limit: 20, // default 50, max 100 }); // Get a specific run const run = await client.automations.run(appId, runId); console.log(run.status); // "completed" console.log(run.result); // { payload: {...}, output: [...] } ``` ```bash archastro list automationruns --automation aut_abc123 archastro list automationruns --automation aut_abc123 --status failed archastro describe automationrun atr_abc123 ``` ### Run results On success, the `result` field contains: ```json { "payload": { /* final workflow output value */ }, "output": ["line 1 from println", "line 2 from println"] } ``` On failure: ```json { "error": "Script execution timed out" } ``` --- ## Automation properties | Field | Type | Description | |-------|------|-------------| | `id` | string | Automation ID (`aut_` prefix) | | `name` | string | Display name (required) | | `description` | string | Optional description | | `type` | enum | `trigger` or `scheduled` | | `status` | enum | `draft`, `running`, or `paused` | | `trigger` | string | Event name (required for trigger type) | | `schedule` | string | Cron expression (required for scheduled type) | | `config_id` | string | WorkflowGraph config to execute | | `run_as_user_id` | string | Optional user identity for execution context | | `lookup_key` | string | Optional unique slug per app | | `metadata` | object | Arbitrary metadata | --- ## Automations vs. routines Both automations and routines react to events, but they serve different purposes: | | Automations | Routines | |---|---|---| | Scope | App-level | Agent-level | | ID prefix | `aut_` | `arn_` | | Handler types | WorkflowGraph only | WorkflowGraph, Script, or Preset | | Managed by | Developer (portal, SDK, CLI) | Developer per-agent | | Use case | App-wide orchestration, scheduled jobs | Agent behavior and personality | | Status values | `draft` / `running` / `paused` | `draft` / `active` / `paused` | Use automations for cross-cutting concerns (daily reports, event-driven workflows, data pipelines). Use routines for agent-specific behavior (how an agent responds to messages, memory capture, participation patterns). --- ## 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 lifecycle 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 ``` --- ## API reference ### Automation management | Operation | Endpoint | Description | |-----------|----------|-------------| | List | `GET /apps/:app_id/automations` | List automations (optional `?type=` filter) | | Create | `POST /apps/:app_id/automations` | Create an automation | | Show | `GET /apps/:app_id/automations/:id` | Get automation details | | Update | `PATCH /apps/:app_id/automations/:id` | Update an automation | | Delete | `DELETE /apps/:app_id/automations/:id` | Delete an automation | | Activate | `POST /apps/:app_id/automations/:id/activate` | Set status to `running` | | Pause | `POST /apps/:app_id/automations/:id/pause` | Set status to `paused` | | Events | `GET /apps/:app_id/automations/events` | List available event types | ### Automation runs | Operation | Endpoint | Description | |-----------|----------|-------------| | List | `GET /apps/:app_id/automations/:id/runs` | List runs (optional `?status=` filter, cursor pagination) | | Show | `GET /apps/:app_id/automations/runs/:run_id` | Get run details | --- ## Design patterns ### Event-driven onboarding Trigger a workflow when a new user joins a thread to send a welcome message and configure agent behavior: ```ts await client.automations.create(appId, { name: "Onboarding Flow", type: "trigger", trigger: "thread.member_joined", config_id: "cfg_onboarding_workflow", }); ``` ### Scheduled reporting Run a daily workflow that aggregates activity and posts a summary to a team thread: ```ts await client.automations.create(appId, { name: "Daily Activity Report", type: "scheduled", schedule: "0 9 * * 1-5", // 9am UTC, weekdays config_id: "cfg_daily_report", run_as_user_id: "usr_reporter", }); ``` ### Context ingestion monitoring React to context ingestion failures to alert the team or trigger a retry: ```ts await client.automations.create(appId, { name: "Ingestion Failure Alert", type: "trigger", trigger: "context.ingestion.failed", config_id: "cfg_ingestion_alert", }); ``` --- ### Computer Use URL: https://staging.docs.archastro.ai/docs/computer-use Summary: Provision remote machines and execute development or operational tasks through ArchAstro-managed environments. ## Overview Computer Use lets agents provision and control remote Linux machines. Agents can execute shell commands, read and write files, and complete development or operational tasks through the platform API or built-in AI tools. Computers remain available across commands, so agents can complete multi-step workflows over time instead of starting from scratch for every action. --- ## Provisioning a computer Create a computer for an agent through the SDK or API: ```ts const computer = await client.rest.createAgentComputer(agent.id, { name: "dev-machine", lookup_key: "primary", region: "iad", metadata: { purpose: "ci-runner", }, }); console.log("Computer:", computer.id); console.log("Status:", computer.status); ``` Provisioning is asynchronous. The computer starts in `pending`, moves through `provisioning`, and becomes `ready` when it can accept commands. ### Computer statuses | Status | Meaning | |--------|---------| | `pending` | Created, not yet provisioned | | `provisioning` | Environment setup in progress | | `ready` | Live and accepting commands | | `error` | Provisioning failed | | `destroyed` | Marked for deletion | ### Computer properties | Field | Type | Description | |-------|------|-------------| | `id` | string | Computer ID | | `name` | string | Display name | | `lookup_key` | string | Unique per agent | | `status` | enum | Current state | | `region` | string | Deployment region | | `config` | object | Custom configuration | | `metadata` | object | Arbitrary metadata | | `error_message` | string | Error details if provisioning failed | | `last_active_at` | datetime | Last command execution time | --- ## Executing commands Once a computer is ready, execute shell commands: ```ts const result = await client.rest.execComputerCommand(computer.id, { command: "git clone https://github.com/org/repo.git && cd repo && npm test", dir: "/home/sprite", }); console.log("Output:", result.output); console.log("Exit code:", result.exit_code); console.log("Status:", result.status); ``` Commands run with a timeout, and the working directory defaults to the computer's home directory. ### Environment Computers provide a Linux development environment suitable for common scripting, repository, and build tasks. Typical capabilities include: - source checkout and file operations - package installation and dependency management - test and build execution - multi-step scripted workflows over persistent files Use Computer Use only where it fits your security, approval, and operational model. --- ## AI tools Agents can use computers during conversations through three 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 | ### Tool resolution When an agent uses computer tools, the platform automatically routes the request to a ready computer associated with that agent. --- ## Managing computers ```ts const computers = await client.rest.listAgentComputers(agent.id); const computer = await client.rest.getAgentComputer(computerId); await client.rest.refreshAgentComputer(computerId); await client.rest.destroyAgentComputer(computerId); ``` --- ## API reference | Operation | Endpoint | Description | |-----------|----------|-------------| | Create | `POST /agents/:id/computers` | Provision a new computer | | List | `GET /agents/:id/computers` | List computers for an agent | | Show | `GET /agents/:id/computers/:computer_id` | Get computer details | | Exec | `POST /agent_computers/:computer_id/exec` | Execute a command | | Refresh | `POST /agent_computers/:computer_id/refresh` | Refresh status | | Delete | `DELETE /agents/:id/computers/:computer_id` | Destroy a computer | --- ## Design patterns ### Build and test runner An agent provisions a computer, checks out a codebase, runs validation commands, and reports the result back to a thread. ### Review assistant An agent pulls a change, runs checks, and summarizes findings for a human reviewer. ### Operational automation An agent performs recurring scripted diagnostics or maintenance tasks and reports anomalies to the relevant team. --- ### Scripts URL: https://staging.docs.archastro.ai/docs/scripts Summary: Write custom runtime logic for data shaping, policy checks, adapter code, and workflow nodes. ## Overview Scripts let you run custom logic inside the ArchAstro runtime. Use them when generic workflow nodes are not enough for data transformation, policy enforcement, adapter logic, conditional routing, or custom validation. Scripts can run as standalone logic, within routines, or as nodes in workflows. They are stored as versioned configs and edited in the portal. --- ## Writing scripts ### In the portal 1. Navigate to **Scripts** under your app. 2. Click **New Script**. 3. Write your code in the editor. 4. Select a **Run as User** context. 5. Click **Run** to test. 6. Click **Save** to create a new version. Every save creates a new version. You can review earlier versions and revert when needed. ### Via the API Scripts participate in the public developer surface through workflow execution, workflow metadata, configs, and other app-scoped resources. The reviewed external endpoint list is published at [`/openapi.json`](/openapi.json). ```json { "script": "const total = input.items.reduce((sum, i) => sum + i.price, 0); return { total, count: input.items.length };", "input": { "items": [ { "name": "Widget", "price": 29.99 }, { "name": "Gadget", "price": 49.99 } ] } } ``` --- ## How scripts are used | Context | How it works | |---------|-------------| | **Routine handler** | Use a script as the code executed when a routine fires | | **Workflow node** | Add a script node to a workflow | | **Standalone** | Execute through the API or portal run flow | | **Custom tool** | Back a tool with app-specific logic | --- ## Scripts vs expressions | Feature | Script | Expression | |---------|--------|------------| | Multi-statement logic | Yes | No | | Return values | Explicit `return` | Implicit evaluation | | Side effects | Possible | No | | Use in workflows | Standalone nodes | Inline conditions | | Complexity | Flexible | Simple data access and conditions | Use expressions for simple conditions. Use scripts when you need richer logic, error handling, or multi-step transformations. --- ## Use cases - **Data transformation** — reshape API responses between workflow steps - **Policy enforcement** — validate inputs against business rules before actions proceed - **Adapter logic** — normalize data between systems - **Conditional routing** — evaluate richer branching conditions - **Custom validation** — enforce schema or content requirements on outputs - **Aggregation** — combine data from multiple sources before passing it on --- ### Extensions & Integrations URL: https://staging.docs.archastro.ai/docs/extensions-integrations Summary: Connect OAuth providers, configure webhooks, and build agent capabilities with tools and connectors. ## Overview ArchAstro treats integrations as first-class platform primitives. Agents access external services through **installations** (scoped data connections), users authorize access through **OAuth connectors**, and external systems push events via **webhooks**. This page covers the integration surface end-to-end: OAuth setup, connector flows, webhook configuration, and the tools that agents use to act on connected data. --- ## OAuth providers ### Supported providers | Provider | Key | What agents can access | |----------|-----|----------------------| | Google | `google` | Gmail, Calendar, Drive | | Microsoft | `microsoft` | Outlook, Calendar, OneDrive | | GitHub | `github` | Repos, Issues, PRs, Actions | | Slack | `slack` | Channels, Messages, Users | | X (Twitter) | `x_twitter` | Posts, DMs, Timelines | ### Setting up OAuth in the portal 1. Go to **OAuth** → **Providers** under your app 2. Click **Configure** on the provider you want 3. Enter the **Client ID** and **Client Secret** from the provider's developer console 4. The platform auto-configures callback URLs and scopes 5. Save the configuration Once configured, users in your app can connect their accounts through the connector OAuth flow. ### Connector flow (user-facing) The connector flow is how end users authorize access to their external accounts. The SDK handles this end-to-end: ```ts import { buildConnectorAuthorizeUrl } from "@archastro/sdk"; // Generate the OAuth authorization URL const url = await buildConnectorAuthorizeUrl("google", { restApi: client.rest, teamId: teamId, accessLevel: "full_access", webRedirect: "https://yourapp.com/auth/callback", }); // Redirect the user to `url` // After authorization, they're redirected back to your app ``` Check connection state: ```ts const state = await client.rest.getConnectorState("google", teamId); // { connected: true, scopes: ["gmail.readonly", "calendar.events"], ... } ``` Or check per-user: ```ts const state = await client.rest.getUserConnectorState("google"); ``` Disconnect: ```ts await client.rest.disconnectConnector("google", { teamId }); ``` ### OAuth API endpoints **User-scoped connector endpoints:** ``` GET /api/v2/users/:user_id/connectors/:provider/state # Check state POST /api/v2/users/:user_id/connectors/:provider/handoff # Start OAuth DELETE /api/v2/users/:user_id/connectors/:provider # Disconnect ``` Team-scoped connectors use the same pattern under `/api/v2/teams/:team_id/connectors/`. **Handoff request:** ```json { "access_level": "readwrite", "services": ["gmail", "calendar"], "return_to": "/account" } ``` Returns `{ authorize_url: "https://accounts.google.com/..." }` — redirect the user there. **Browser-based OAuth endpoints:** ``` GET /auth/:provider # Start OAuth login GET /auth/:provider/callback # OAuth callback GET /auth/federated/:provider/authorize # Federated OAuth GET /auth/federated/:provider/callback # Federated callback GET /connect/:provider/authorize # Connector OAuth GET /connect/:provider/callback # Connector callback ``` **OAuth server endpoints:** ``` GET /oauth/scopes # List available scopes POST /oauth/token # Exchange tokens POST /oauth/device/authorize # Device flow start POST /oauth/device/approve # Approve device ``` --- ## GitHub App integration GitHub App integration provides a deeper connection to GitHub than the standard OAuth connector. Instead of acting on behalf of a single user, a GitHub App is installed at the organization or repository level and receives events and permissions independently. ### How it works 1. The developer registers a GitHub App in the GitHub developer settings 2. The developer configures the GitHub App's webhook URL to point to ArchAstro (see below) 3. A user installs the GitHub App on their GitHub org or repos 4. GitHub sends installation and repository events to ArchAstro 5. ArchAstro links the GitHub installation to your app 6. Connected agents can use GitHub capabilities based on the installation's permissions ### Installation record GitHub App installations use the following kind and category: | Field | Value | |-------|-------| | `kind` | `integration/github_app` | | `category` | `integration` | | `requires_integration` | `true` | Because `requires_integration` is true, the installation only activates after a matching integration is connected with valid credentials. ### Webhook processing GitHub App events are delivered to a global endpoint rather than the per-app webhook endpoint used by standard provider webhooks: ``` POST /webhooks/github_app ``` **Verification:** Every incoming request is verified using HMAC-SHA256. The platform computes the signature over the raw request body using the GitHub App's webhook secret and compares it against the `X-Hub-Signature-256` header. Requests that fail verification are rejected with a 401. After verification, ArchAstro processes events asynchronously by type (`installation`, `push`, `pull_request`, `issues`, etc.). Common event flows: - **`installation` / `installation_repositories`** — creates or updates Integration records when users install or modify the app - **`push`** — triggers source ingestion for connected repositories - **`pull_request`** / **`issues`** — can trigger agent routines or update context items ### GitHub capabilities for agents When a GitHub App installation is active, ArchAstro makes GitHub capabilities available to the agent automatically based on installation scope and permissions. If an agent has both a custom tool and an auto-provided GitHub capability with the same function, the custom tool is used. Example of tools that might be derived from a GitHub App installation: | Tool key | Description | |----------|-------------| | `github_create_issue` | Create an issue in a connected repository | | `github_list_pull_requests` | List open PRs for a repository | | `github_get_file_contents` | Read file contents from a branch | | `github_create_comment` | Comment on an issue or PR | These capabilities are available without extra setup once the GitHub App installation is active and credentials are valid. ### Comparison with OAuth connector | | OAuth connector (`github`) | GitHub App (`integration/github_app`) | |---|---|---| | **Auth scope** | Per-user | Per-org or per-repo | | **Token type** | User OAuth token | App installation token | | **Receives webhooks** | Via standard webhook config | Via global `/webhooks/github_app` endpoint | | **Best for** | User-scoped actions (PRs, commits as user) | Org-wide automation (CI, bots, repo management) | Use the OAuth connector when agents need to act as a specific user. Use the GitHub App integration when agents need org-level access or need to receive repository events. --- ## Slack Bot The ArchAstro Slack Bot brings your agents directly into Slack. Once an org admin installs the bot, team members can talk to agents by mentioning `@archastro` in any channel — no per-channel setup required. ### Installing the bot An org admin connects the bot from the **Context → Integrations** page in the developer portal by clicking **Connect Slack**. This redirects to Slack's OAuth consent screen. After approval, the bot is installed in the workspace and appears as a new integration in the list. Once installed, invite `@archastro` to the Slack channels where you want agents to be available. ### Talking to agents Mention `@archastro` followed by an agent name and your message: ```text @archastro @DeployBot what's the status of the staging deploy? ``` The bot immediately shows a thinking indicator while the agent processes the request, then replaces it with the real response. If you don't specify an agent name, the bot checks whether the channel has a default agent configured. If no agent matches, the bot replies with a list of available agents and example syntax. ### What the bot supports - **Thinking indicator** — immediate feedback while the agent works, replaced in-place with the answer - **Formatted responses** — AI markdown is converted to Slack's native formatting (bold, italic, links, headings, code blocks) - **Per-user memory** — each Slack user is mapped to their own identity so agents remember context per person - **Agent name display** — responses appear under the agent's name (e.g., "DeployBot") rather than a generic bot name - **Proactive messages** — agents can broadcast scheduled or event-driven messages to configured Slack channels ### Slack Bot vs. Slack OAuth connector | | OAuth connector (`slack`) | Slack Bot (`slack_bot`) | |---|---|---| | **Purpose** | Read a user's Slack history as agent context | Two-way agent conversations in Slack | | **Installed by** | Individual users | Org admin (once per workspace) | | **Use case** | Search past messages, channels, DMs | Ask agents questions, receive answers in Slack | Use the OAuth connector when agents need to search a user's Slack data. Use the Slack Bot when you want agents to be accessible directly in Slack channels. --- ## Webhooks Webhooks let external systems push events to your app. ArchAstro supports provider-specific webhooks with built-in signature validation and generic webhooks for any system. ### Provider webhooks Provider webhooks have built-in signature verification: - **GitHub** — validates `X-Hub-Signature-256` - **Slack** — validates Slack signing secret Create a provider webhook: ```bash curl -X POST "https://api.archastro.ai/protected/api/v2/developer/apps/${ARCHASTRO_APP_ID}/webhooks" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" \ -d '{ "provider": "github", "signing_secret": "whsec_..." }' ``` ### Generic webhooks Generic webhooks work with any system that can POST JSON. Instead of a provider, you specify a `lookup_key`: ```bash curl -X POST "https://api.archastro.ai/protected/api/v2/developer/apps/${ARCHASTRO_APP_ID}/webhooks" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" \ -d '{ "lookup_key": "billing-events", "signing_secret": "'"${BILLING_WEBHOOK_SECRET}"'" }' ``` Use generic webhooks for third-party vendors, CRM systems, payment processors, and any service that can POST JSON. ### Inbound delivery All webhooks (provider and generic) are delivered to: ``` POST /webhooks/:app_id/:provider_or_key ``` ArchAstro validates signatures, stores delivery events, and processes them asynchronously. Failed events are retried. ### Webhook management API ```text GET /protected/api/v2/developer/apps/:app_id/webhooks POST /protected/api/v2/developer/apps/:app_id/webhooks GET /protected/api/v2/developer/apps/:app_id/webhooks/:id PATCH /protected/api/v2/developer/apps/:app_id/webhooks/:id DELETE /protected/api/v2/developer/apps/:app_id/webhooks/:id GET /protected/api/v2/developer/apps/:app_id/webhooks/:id/events ``` ### Webhook management via CLI ```bash archastro list appwebhooks archastro create appwebhook -p github -s my_signing_secret archastro describe appwebhook webhook_abc123 archastro update appwebhook webhook_abc123 --enabled false archastro delete appwebhook webhook_abc123 ``` --- ## Integration actions Once a user has connected a provider, agents can execute actions on the connected service: ```ts // List connected integrations const integrations = await client.rest.listIntegrations(); // List available actions for a provider const actions = await client.rest.listProviderActions("google"); // Execute an action await client.rest.runAction("google", "send_email", { to: "user@example.com", subject: "Follow-up", body: "Here's the information you requested.", }); ``` For the exact currently published external API surface for integrations and connector operations, use [`/openapi.json`](/openapi.json). --- ## OAuth clients (third-party apps) If you want third-party applications to authenticate against your ArchAstro app using OAuth, enable third-party OAuth in the portal: 1. Go to **OAuth** → **Clients** 2. Toggle **Enable Third-Party OAuth** 3. Click **Register Client** 4. Enter client name, scopes, and redirect URIs 5. Copy the client credentials (shown once) Registered clients can then use standard OAuth flows to obtain tokens scoped to your app. --- ## How integrations connect to agents The full integration flow for an agent: ``` 1. Developer configures OAuth provider (portal) 2. Developer creates an installation on an agent (kind: integration/gmail) 3. User completes OAuth connector flow (browser) 4. Platform stores encrypted credentials (Integration record) 5. Installation activates → Sources auto-created 6. Sources begin ingesting data (emails, events, repos) 7. Agent's context fills with searchable items 8. Agent can now search and act on the connected data ``` This architecture separates concerns clearly: - **OAuth providers** — configured once per app by the developer - **Installations** — connect a specific agent to a specific data source - **Integrations** — store per-user OAuth credentials - **Sources** — track individual data retrieval tasks - **Tools** — let agents take actions on connected services --- ### API Reference URL: https://staging.docs.archastro.ai/docs/api-reference Summary: External API reference for authentication, runtime resources, and developer control-plane operations. **Base URL:** `https://api.archastro.ai` The ArchAstro API is organized into three externally documented scope families: - **Public auth** for login, OAuth, and token exchange - **Runtime** for user and team resources such as threads, messages, tasks, and connected services - **Developer control-plane** for app configuration, agents, routines, workflows, webhooks, and other developer operations under the reviewed developer surface For the machine-readable external API surface, use [`/openapi.json`](/openapi.json). --- ## API scopes ### Public auth scope - `/api/v2/auth/...` - `/oauth/...` ### Runtime scopes - `/api/v2/users/...` - `/api/v2/teams/...` - `/api/v2/agents/...` - `/api/v2/connectors/...` - selected top-level runtime endpoints such as `/api/v2/scrape`, `/api/v2/search`, and `/api/v2/feedback` ### Developer control-plane scope - `/protected/api/v2/developer/me` - `/protected/api/v2/developer/invites/:token/accept` - `/protected/api/v2/developer/apps` - reviewed app-scoped families under `/protected/api/v2/developer/apps/:app_id/...` Internal-only observability, analytics, and execution-debug helpers are intentionally excluded from the public docs artifact even when they exist internally. --- ## Authentication ### API keys | Key Type | Prefix | Use | |----------|--------|-----| | Publishable | `pk_live_` | Client initialization | | Secret | `sk_live_` | Trusted server operations | Create keys in [developers.archastro.ai](https://developers.archastro.ai). ### Headers Use one of: ```http Authorization: Bearer ``` ```http x-api-key: ``` For user actions after login, use JWT access tokens in `Authorization`. --- ## Auth flows - `POST /api/v2/auth/register` - `POST /api/v2/auth/login` - `POST /api/v2/auth/login/link` - `POST /api/v2/auth/verify/link` - `POST /api/v2/auth/login/code` - `POST /api/v2/auth/code/verify` - `POST /api/v2/auth/refresh` - `POST /api/v2/auth/oauth` - `POST /api/v2/auth/token` - `POST /oauth/device/authorize` - `POST /oauth/token` Use device flow for CLI and other non-browser clients. --- ## Developer control-plane surface These app-scoped endpoints are available from `@archastro/sdk` and the developer portal. ### Agents ```text GET /protected/api/v2/developer/apps/:app_id/agents POST /protected/api/v2/developer/apps/:app_id/agents GET /protected/api/v2/developer/apps/:app_id/agents/:agent_id PATCH /protected/api/v2/developer/apps/:app_id/agents/:agent_id DELETE /protected/api/v2/developer/apps/:app_id/agents/:agent_id ``` ### Teams and organizations ```text GET /protected/api/v2/developer/apps/:app_id/teams POST /protected/api/v2/developer/apps/:app_id/teams GET /protected/api/v2/developer/apps/:app_id/teams/:team_id PATCH /protected/api/v2/developer/apps/:app_id/teams/:team_id GET /protected/api/v2/developer/apps/:app_id/teams/:team_id/members POST /protected/api/v2/developer/apps/:app_id/teams/:team_id/members DELETE /protected/api/v2/developer/apps/:app_id/teams/:team_id/members/:user_id GET /protected/api/v2/developer/apps/:app_id/orgs POST /protected/api/v2/developer/apps/:app_id/orgs GET /protected/api/v2/developer/apps/:app_id/orgs/:id PATCH /protected/api/v2/developer/apps/:app_id/orgs/:id DELETE /protected/api/v2/developer/apps/:app_id/orgs/:id ``` ### Routines, workflows, and automations ```text GET /protected/api/v2/developer/apps/:app_id/routines POST /protected/api/v2/developer/apps/:app_id/agents/:agent_id/routines PATCH /protected/api/v2/developer/apps/:app_id/routines/:routine_id POST /protected/api/v2/developer/apps/:app_id/routines/:routine_id/activate POST /protected/api/v2/developer/apps/:app_id/routines/:routine_id/pause POST /protected/api/v2/developer/apps/:app_id/workflows/run GET /protected/api/v2/developer/apps/:app_id/workflows/node-types GET /protected/api/v2/developer/apps/:app_id/workflows/scripts/language ``` ### Installations and context ```text GET /protected/api/v2/developer/apps/:app_id/installations GET /protected/api/v2/developer/apps/:app_id/installations/kinds POST /protected/api/v2/developer/apps/:app_id/agents/:agent_id/installations POST /protected/api/v2/developer/apps/:app_id/installations/:installation_id/activate GET/POST /protected/api/v2/developer/apps/:app_id/context/sources GET/POST /protected/api/v2/developer/apps/:app_id/context/integrations GET/POST /protected/api/v2/developer/apps/:app_id/context/credentials ``` ### Other common developer surfaces Also available under reviewed app-scoped families such as `/protected/api/v2/developer/apps/:app_id/...`: - `configs` - `webhooks` - `oauth_providers` - `oauth_clients` - `keys` - `domains` - `files` - `custom_objects` - `sandboxes` - `users` - `members` - `personas` --- ## Runtime surface ### Users ```text GET /api/v2/users/me GET /api/v2/users/:user_id PATCH /api/v2/users/:user_id/profile PATCH /api/v2/users/:user_id/email PATCH /api/v2/users/:user_id/timezone ``` ### Agents ```text GET /api/v2/agents POST /api/v2/agents GET /api/v2/agents/:agent_id PATCH /api/v2/agents/:agent_id DELETE /api/v2/agents/:agent_id ``` ### Threads ```text GET /api/v2/users/:user_id/threads POST /api/v2/users/:user_id/threads GET /api/v2/users/:user_id/threads/:thread_id PATCH /api/v2/users/:user_id/threads/:thread_id DELETE /api/v2/users/:user_id/threads/:thread_id GET /api/v2/teams/:team_id/threads POST /api/v2/teams/:team_id/threads GET /api/v2/teams/:team_id/threads/:thread_id PATCH /api/v2/teams/:team_id/threads/:thread_id DELETE /api/v2/teams/:team_id/threads/:thread_id ``` ### Messages ```text GET /api/v2/users/:user_id/threads/:thread_id/messages POST /api/v2/users/:user_id/threads/:thread_id/messages GET /api/v2/teams/:team_id/threads/:thread_id/messages POST /api/v2/teams/:team_id/threads/:thread_id/messages ``` ### Teams, memberships, and invitations ```text GET /api/v2/teams POST /api/v2/teams GET /api/v2/teams/:team_id PUT /api/v2/teams/:team_id GET /api/v2/teams/:team_id/members POST /api/v2/teams/:team_id/invite POST /api/v2/teams/join ``` ### Tasks, objects, artifacts, and integrations Representative runtime endpoints include: ```text GET /api/v2/teams/:team_id/tasks GET /api/v2/teams/:team_id/objects POST /api/v2/scrape POST /api/v2/search POST /api/v2/feedback GET /api/v2/users/:user_id/integrations POST /webhooks/:app_id/:provider_or_key ``` --- ## WebSocket channels Real-time communication uses WebSocket channels. **Connection URL:** `wss://api.archastro.ai/socket/websocket` | Topic | Purpose | |-------|---------| | `user:` | User presence, notifications, direct events | | `team:` | Team-wide events and member activity | | `thread:` | Thread messages, typing indicators, and agent responses | --- ## Pagination The API uses both cursor-based and offset-based pagination depending on the resource type. Examples: ```http GET /api/v2/users/:user_id/threads/:thread_id/messages?limit=50&before_cursor=msg_abc123 ``` ```http GET /api/v2/teams/:team_id/tasks?limit=25&offset=0 ``` --- ## Error format All errors return a consistent JSON structure: ```json { "error": { "code": "not_found", "message": "Thread not found", "details": {} } } ``` **Common HTTP status codes:** | Code | Meaning | |------|---------| | `400` | Invalid request | | `401` | Authentication required | | `403` | Forbidden | | `404` | Resource not found | | `422` | Validation failed | | `500` | Internal server error | --- ### Samples URL: https://staging.docs.archastro.ai/docs/samples Summary: Complete, runnable code examples for common agent patterns — from bootstrap to production. ## Overview Each example is self-contained with prerequisites listed. Copy them directly into your project. --- ## Agent bootstrap script Create an agent with a routine in a single executable script. **Prerequisites:** `npm install @archastro/sdk tsx`, set `ARCHASTRO_SECRET_KEY` ```ts // src/agents/bootstrap.ts import { ArchAstroClient } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; // Create agent identity const agent = await client.rest.createAgent({ name: "Support Agent", lookup_key: "support", identity: "You are a customer support specialist for Acme Corp.", }); console.log("Agent:", agent.id); // Attach event-driven routine const routine = await client.rest.createAgentRoutine({ agent_id: agent.id, name: "message_handler", event_type: "thread.message_added", handler_type: "script", script: ` const msg = event.payload.message; const intent = msg.text.toLowerCase().includes("billing") ? "billing" : "general"; return { intent, agent_id: "${agent.id}" }; `, }); console.log("Routine:", routine.id); console.log("\nAgent ready. Activate the routine in the portal or via API."); await client.dispose(); } main().catch(console.error); ``` ```bash npx tsx src/agents/bootstrap.ts ``` --- ## Next.js server auth Server-side authentication with session management and federated login. **Prerequisites:** `npm install @archastro/sdk @archastro/sdk-nextjs`, set `ARCHASTRO_SECRET_KEY` and `SESSION_SECRET` ```ts // src/lib/auth.ts import { createSessionManager, createAuthActions, } from "@archastro/sdk-nextjs/server"; export const sessionManager = createSessionManager({ secretKey: process.env.SESSION_SECRET!, cookieName: "archastro_session", }); export const authActions = createAuthActions({ sessionManager, apiKey: process.env.ARCHASTRO_SECRET_KEY!, }); ``` ```ts // src/lib/federated-auth.ts import { createFederatedAuth } from "@archastro/sdk-nextjs/server"; import { sessionManager } from "./auth"; export const federatedAuth = createFederatedAuth({ providers: ["google", "github"], sessionManager, apiKey: process.env.ARCHASTRO_SECRET_KEY!, }); ``` ```ts // src/app/api/auth/[...route]/route.ts import { authActions } from "@/lib/auth"; export const POST = authActions.handler; export const GET = authActions.handler; ``` --- ## Real-time chat with agents Join a thread and interact with agents in real time. **Prerequisites:** `npm install @archastro/sdk`, set `ARCHASTRO_SECRET_KEY` ```ts // src/chat/realtime-demo.ts import { ArchAstroClient, ChatRoomService } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; // Create a team and thread const teams = await client.rest.listTeams(); const teamId = teams[0].id; const thread = await client.rest.createThread(teamId, "Agent demo"); console.log("Thread:", thread.id); // Connect via WebSocket const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(teamId, thread.id); // Listen for all message events room.on("message_added", (e) => { const sender = e.message.actor?.name || "Unknown"; console.log(`[${sender}] ${e.message.content}`); }); room.on("message_updated", (e) => { console.log(`[Edited] ${e.message.content}`); }); // Send a message await room.postMessage("Hello, I need help with my account"); // Keep alive for demo console.log("Listening for messages... (Ctrl+C to exit)"); } main().catch(console.error); ``` --- ## Agent conversation (direct) Start a direct agent conversation using the `AgentConversationService`. **Prerequisites:** `npm install @archastro/sdk`, set `ARCHASTRO_SECRET_KEY` ```ts // src/chat/agent-conversation.ts import { ArchAstroClient } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; const teams = await client.rest.listTeams(); const session = await client.socket.agentConversationService .joinConversation({ scope: "team", teamId: teams[0].id, }); console.log("Session:", session.getSessionId()); // Listen for agent responses session.onEvent((event) => { switch (event.type) { case "message_added": console.log(`Agent: ${event.message.content}`); break; case "session_ended": console.log(`Session ended: ${event.reason}`); break; } }); // Send a message await session.sendMessage({ content: "What can you help me with?" }); console.log("Message sent, waiting for response..."); } main().catch(console.error); ``` --- ## Multi-agent network Create two agents that collaborate in a shared thread using participate routines. **Prerequisites:** `npm install @archastro/sdk tsx`, set `ARCHASTRO_SECRET_KEY` ```ts // src/agents/multi-agent-network.ts import { ArchAstroClient, ChatRoomService } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function main() { await client.ready; // Create two agents with complementary roles const researcher = await client.rest.createAgent({ name: "Research Agent", lookup_key: "researcher", identity: "You are a research specialist. Find relevant information " + "and provide thorough analysis with cited sources.", }); const writer = await client.rest.createAgent({ name: "Writer Agent", lookup_key: "writer", identity: "You are a writing specialist. Take research findings " + "and synthesize them into clear, actionable summaries.", }); // Create a team and add both agents const team = await client.rest.createTeam({ name: "Research & Writing" }); await client.rest.addTeamMember(team.id, { agent_id: researcher.id, role: "member", }); await client.rest.addTeamMember(team.id, { agent_id: writer.id, role: "member", }); // Create a shared thread const thread = await client.rest.createThread(team.id, "Analysis"); // Attach participate routines for (const agent of [researcher, writer]) { await client.rest.createAgentRoutine({ agent_id: agent.id, name: `${agent.name}_participate`, event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); } // Observe in real time const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(team.id, thread.id); room.on("message_added", (e) => { console.log(`[${e.message.actor?.name}] ${e.message.content}`); }); await room.postMessage("Research AI agent frameworks and summarize the top 3."); console.log("Conversation started. Thread:", thread.id); } main().catch(console.error); ``` ```bash npx tsx src/agents/multi-agent-network.ts ``` For more patterns and cross-org examples, see [Agent Network](/docs/agent-network) and [Networks](/docs/networks). --- ## Generic webhook receiver Set up a webhook to receive events from an external billing system. **Prerequisites:** Set `ARCHASTRO_SECRET_KEY` and `ARCHASTRO_APP_ID` ```bash # Create the webhook with a lookup key curl -X POST "https://api.archastro.ai/protected/api/v2/developer/apps/${ARCHASTRO_APP_ID}/webhooks" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" \ -d '{ "lookup_key": "billing-events", "signing_secret": "whsec_your_secret_here" }' ``` External systems send events to: ``` POST https://api.archastro.ai/webhooks//billing-events ``` List recent events: ```bash # Via CLI archastro describe appwebhook # Or via API curl "https://api.archastro.ai/protected/api/v2/developer/apps/${ARCHASTRO_APP_ID}/webhooks//events" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" ``` --- ## OAuth connector flow Let users connect their Google account to your app. **Prerequisites:** Configure Google OAuth provider in the portal first ```ts // src/connectors/google.ts import { ArchAstroClient, buildConnectorAuthorizeUrl } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); async function connectGoogle(teamId: string) { // Generate OAuth URL const url = await buildConnectorAuthorizeUrl("google", { restApi: client.rest, teamId, accessLevel: "full_access", webRedirect: "https://yourapp.com/connectors/callback", }); console.log("Redirect user to:", url); // After authorization, check state: const state = await client.rest.getConnectorState("google", teamId); console.log("Connected:", state.connected); console.log("Scopes:", state.scopes); } ``` --- ## Config validation Validate a YAML config before deploying it to production. ```bash # Via API curl -X POST "https://api.archastro.ai/api/v2/config/validate" \ -H "Authorization: Bearer ${ARCHASTRO_SECRET_KEY}" \ -H "Content-Type: application/json" \ -d '{ "kind": "AIWorker", "content": "kind: AIWorker\nid: my_assistant\nmodel: claude-sonnet-4-5-20250929" }' ``` ```bash # Via CLI archastro configs validate -k AIWorker --content "kind: AIWorker\nid: my_assistant" ``` --- ## Secrets management Store and retrieve encrypted secrets at different scopes. ```ts // Personal secret await client.rest.createPersonalSecret({ name: "openai_key", value: "sk-...", description: "OpenAI API key for agent completions", }); const secret = await client.rest.getPersonalSecretValue("openai_key"); console.log("Value:", secret.value); // Team secret await client.rest.createTeamSecret(teamId, { name: "stripe_key", value: "sk_live_...", description: "Stripe API key", }); // Update await client.rest.updatePersonalSecret("openai_key", { value: "sk-new-key...", }); // Delete await client.rest.deletePersonalSecret("openai_key"); ``` --- ## CLI: full workflow End-to-end workflow using only the CLI. ```bash # 1. Initialize project archastro init # 2. Create an agent archastro create agent -n "Support Bot" -k support \ -i "You are a helpful support agent" # 3. Create a team and user archastro create team -n "Support Team" archastro create user -e customer@example.com -n "Test Customer" archastro create user --system-user # bot service account # 4. Create an automation archastro create automation -n "Welcome" -t trigger --trigger "user.created" # 5. Set up a webhook archastro create appwebhook -p github -s my_secret # 6. Sync and deploy configs archastro configs sync archastro configs deploy -m "Initial setup" # 7. Check status archastro list agents --json archastro list automations archastro auth status ``` --- ### CLI URL: https://staging.docs.archastro.ai/docs/cli Summary: Manage apps, agents, configs, and operations from the command line with the archastro CLI. ## Overview The ArchAstro CLI provides command-line access to every platform operation. It uses a **verb-first syntax** (`archastro `) and supports `--json` output for scripting and CI/CD pipelines. --- ## Installation ```bash # Configure npm registry for @archastro scope # Add to ~/.npmrc: @archastro:registry=https://npm.pkg.github.com //npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN ``` ```bash npm install -g @archastro/developer-platform-cli ``` Verify: ```bash archastro --help ``` --- ## Authentication The CLI uses browser-based OAuth device flow: ```bash archastro auth login ``` This opens your browser to `developers.archastro.ai/cli-auth`, starts a local callback server, and stores credentials in `~/.config/archastro/credentials.json` (mode 0600). Tokens are scoped per-app and refreshed automatically. ```bash archastro auth status # Show current auth state archastro auth logout # Remove all stored credentials ``` --- ## Project initialization ```bash cd my-project archastro init ``` `init` opens your browser for app selection (or creation), generates API keys, and writes `archastro.json` to your project root: ```json { "app_id": "app_abc123", "sandbox_id": "sbx_optional", "configs": { "enabled": true, "directory": "configs" } } ``` --- ## Settings ```bash archastro settings get # Show all settings archastro settings set app # Set default app archastro settings set api-url # Override API URL archastro settings set portal-url archastro settings reset # Reset to defaults archastro settings path # Show config file path ``` --- ## Resource commands All resources support a consistent verb pattern: ### Apps ```bash archastro list apps archastro describe app ``` ### API keys ```bash archastro list appkeys archastro create appkey -t publishable # or -t secret archastro revoke appkey ``` Secret keys are shown once at creation — copy immediately. ### Agents ```bash archastro list agents archastro list agents --search "support" archastro describe agent archastro create agent -n "Support Agent" -k support-bot \ -i "You are a customer support specialist" archastro create agent -n "Alex" --profile-picture ./avatar.png archastro update agent -n "Senior Support Agent" archastro delete agent ``` Agent flags: `-n/--name`, `-k/--lookup-key`, `-e/--email`, `-p/--phone`, `-i/--identity`, `--team-id`, `--user-id`, `--profile-picture`. ### Users ```bash archastro list users archastro list users --search "john@example.com" archastro describe user archastro create user -e alice@example.com -n "Alice" archastro create user --system-user # bot account, no login archastro delete user ``` ### Teams ```bash archastro list teams archastro list teams --search "engineering" archastro describe team archastro create team -n "Engineering" -d "Engineering department" archastro update team -n "New Name" archastro delete team ``` ### Threads ```bash archastro list threads archastro describe thread ``` ### Automations ```bash archastro list automations archastro list automations --type trigger archastro list automations --type scheduled archastro describe automation archastro create automation -n "Welcome Email" -t trigger --trigger "user.created" archastro create automation -n "Daily Report" -t scheduled --schedule "0 8 * * *" archastro update automation -n "New Name" archastro activate automation archastro pause automation archastro delete automation ``` ### Files ```bash archastro list files archastro list files --team-id archastro describe file archastro create file --data "base64..." --filename "doc.pdf" --content-type "application/pdf" archastro update file --filename "renamed.pdf" ``` ### Environment variables ```bash archastro list appenvvars archastro describe appenvvar archastro create appenvvar -k WEBHOOK_SECRET -v my_secret -d "Webhook signing secret" archastro update appenvvar -v new_value archastro delete appenvvar ``` ### Webhooks ```bash archastro list appwebhooks archastro describe appwebhook archastro create appwebhook -p github -s signing_secret archastro update appwebhook --enabled false archastro delete appwebhook ``` ### OAuth providers ```bash archastro list appoauthproviders archastro describe appoauthprovider archastro create appoauthprovider -p github \ --client-id abc123 --client-secret xyz789 \ --callback-urls "https://app.example.com/auth/github" archastro update appoauthprovider --enabled false archastro delete appoauthprovider ``` ### Domains ```bash archastro list appdomains archastro create appdomain -d example.com archastro delete appdomain ``` --- ## Organization management ```bash archastro list orgs archastro describe org archastro create org -n "Acme Corp" --slug acme --domain acme.com archastro update org -n "Acme Corporation" archastro delete org archastro org invite -e alice@example.com -r developer # or -r admin archastro org remove archastro org invites # list pending ``` --- ## Sandbox management See [Sandboxes](/docs/sandboxes) for the full guide. ```bash archastro list sandboxes # * marks active sandbox archastro describe sandbox archastro create sandbox -n "Staging" -s staging archastro activate sandbox # opens browser to scope CLI to sandbox ``` ### Sandbox keys ```bash archastro list sandboxkeys --sandbox archastro create sandboxkey --sandbox -t publishable # or -t secret archastro revoke sandboxkey --sandbox ``` ### Sandbox emails ```bash archastro list sandboxmails --sandbox archastro describe sandboxmail --sandbox archastro delete sandboxmail --sandbox archastro delete sandboxmails --sandbox --all ``` --- ## Agent extensions ### Agent computers ```bash archastro list agentcomputers --agent archastro describe agentcomputer archastro create agentcomputer --agent archastro delete agentcomputer ``` ### Agent working memory ```bash archastro list agentworkingmemory --agent ``` ### System configs Browse and clone platform-provided config templates. ```bash archastro list systemconfigs archastro describe systemconfig archastro clone systemconfig ``` --- ## Configuration management The CLI can sync configs between your local filesystem and the server, enabling version-controlled config workflows. ### Enable config sync During `archastro init`, opt in to config management. This creates a `configs/` directory and a `.archastro-manifest.json` file that tracks server mappings. ### Pull configs from server ```bash archastro configs sync # pull all archastro configs sync --dry-run # preview changes archastro configs sync --on-conflict overwrite # overwrite local on conflict archastro configs sync --kind api-gateway # sync specific kind archastro configs sync --prune-local # delete locally-tracked configs removed on server ``` ### Push configs to server ```bash archastro configs deploy # push all archastro configs deploy --dry-run # preview changes archastro configs deploy --prune # archive server configs deleted locally archastro configs deploy -m "Update API rules" # with change message ``` ### Other config operations ```bash archastro configs content # show raw content archastro configs kinds # list available kinds archastro configs sample # show sample config archastro configs sample --to-file f.yaml archastro configs validate -k workflow --content "..." archastro configs archive archastro configs edit # open in browser editor archastro configs new [filename] # create in browser editor archastro configs mv # update manifest after move archastro configs manifest-repair # fix manifest inconsistencies ``` --- ## Scripting with JSON output All commands support `--json` for machine-readable output: ```bash # Get all agent IDs archastro list agents --json | jq -r '.data[].id' # Create a user and capture the ID USER_ID=$(archastro create user -e bot@example.com --system-user --json | jq -r '.id') # Pipe to other tools archastro list teams --json | jq '.data[] | select(.name | contains("Eng"))' ``` --- ## Shell completion ```bash eval "$(archastro completion bash)" # add to ~/.bashrc eval "$(archastro completion zsh)" # add to ~/.zshrc archastro completion fish | source # or save to completions dir ``` --- ## Configuration files | File | Purpose | |------|---------| | `~/.config/archastro/config.json` | CLI settings (default app, URLs) | | `~/.config/archastro/credentials.json` | Auth tokens (mode 0600) | | `./archastro.json` | Project config (app ID, sandbox, config sync) | | `./configs/.archastro-manifest.json` | Config sync state | --- ## Environment variables | Variable | Purpose | |----------|---------| | `ARCHASTRO_DEV_API_URL` | Override API base URL | | `ARCHASTRO_DEV_PORTAL_URL` | Override portal URL | --- ## Generated command index The full command index below is auto-generated from the CLI source. --- ### For Coding Agents URL: https://staging.docs.archastro.ai/docs/for-coding-agents Summary: Canonical instructions, stable URLs, and deterministic setup for Claude Code, Codex, Gemini CLI, and other AI coding tools. ## Overview This page is designed for AI coding agents. It provides everything you need to scaffold, build, and operate ArchAstro-powered applications without ambiguity. --- ## Quick setup prompt Paste this into your project root to bootstrap an ArchAstro agent scaffold: ```text Set up ArchAstro agent-first scaffolding in this repo. 1) Install: npm i @archastro/sdk 2) Create: - src/lib/archastro.ts (client initialization) - src/agents/bootstrap-support-agent.ts 3) In src/lib/archastro.ts: import { ArchAstroClient } from "@archastro/sdk"; export const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); 4) In bootstrap-support-agent.ts: - import { client } from "../lib/archastro" - await client.ready - create one agent via client.rest.createAgent({ name: "Support Agent" }) - create one routine via client.rest.createAgentRoutine({ agent_id: agent.id, name: "handler", event_type: "thread.message_added", handler_type: "script", script: "return { handled: true };" }) - print created IDs - call client.dispose() 5) Add npm script: "archastro:bootstrap": "tsx src/agents/bootstrap-support-agent.ts" Use env vars: ARCHASTRO_SECRET_KEY (required) ARCHASTRO_APP_ID (if calling reviewed developer endpoints under /protected/api/v2/developer/apps/:app_id/...) ``` --- ## Required environment variables Before running any ArchAstro operations, check that these are set. **Ask the user for values you don't have.** | Variable | Required | Purpose | |----------|----------|---------| | `ARCHASTRO_SECRET_KEY` | Always | Server-side API authentication (`sk_live_` prefix) | | `ARCHASTRO_APP_ID` | For developer endpoints | App-scoped control-plane operations | | `NEXT_PUBLIC_ARCHASTRO_PK` | Client-side only | Browser SDK initialization (`pk_live_` prefix) | | `SESSION_SECRET` | Next.js SDK only | Session encryption key | Do not proceed with write operations without confirming these values exist. --- ## Canonical URLs | Resource | URL | |----------|-----| | API base | `https://api.archastro.ai` | | Developer portal | `https://developers.archastro.ai` | | Documentation | `https://docs.archastro.ai` | | LLM index | `https://docs.archastro.ai/llms.txt` | | Extended LLM index | `https://docs.archastro.ai/llms-full.txt` | | OpenAPI spec | `https://docs.archastro.ai/openapi.json` | Treat these URLs as canonical. Do not infer or guess alternative endpoints. --- ## SDK packages ```bash npm install @archastro/sdk # core SDK (always required) npm install @archastro/sdk-nextjs # Next.js server helpers npm install -g @archastro/developer-platform-cli # CLI (optional) ``` The CLI currently requires GitHub Packages registry access: ```bash # Add to ~/.npmrc @archastro:registry=https://npm.pkg.github.com //npm.pkg.github.com/:_authToken=GITHUB_TOKEN ``` --- ## Client initialization patterns ### Server-side (secret key) ```ts import { ArchAstroClient } from "@archastro/sdk"; const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", secretKey: process.env.ARCHASTRO_SECRET_KEY!, }); await client.ready; ``` ### Client-side (publishable key) ```ts const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", publishableKey: process.env.NEXT_PUBLIC_ARCHASTRO_PK!, storageStrategy: "secure", }); ``` ### BFF pattern (token provider) ```ts const client = new ArchAstroClient({ baseURL: "https://api.archastro.ai", publishableKey: "pk_live_...", tokenProvider: { async getTokens() { const res = await fetch("/api/auth/session", { credentials: "include" }); return res.ok ? res.json() : null; }, async onAuthExpired() { window.location.href = "/login"; }, }, }); ``` --- ## Core SDK operations ### Agents ```ts const agent = await client.rest.createAgent({ name: "My Agent", lookup_key: "my-agent" }); const agents = await client.rest.listAgents(); await client.rest.updateAgent(agent.id, { name: "Updated" }); await client.rest.deleteAgent(agent.id); ``` ### Routines ```ts const routine = await client.rest.createAgentRoutine({ agent_id: agent.id, name: "handler", event_type: "thread.message_added", handler_type: "script", script: "return { handled: true };", }); ``` ### Threads and messages ```ts const thread = await client.rest.createThread(teamId, "Title"); const messages = await client.rest.getThreadMessages(teamId, thread.id); ``` ### Real-time ```ts import { ChatRoomService } from "@archastro/sdk"; const chat = new ChatRoomService(client.socket); const room = await chat.joinThread(teamId, threadId); room.on("message_added", (e) => console.log(e.message.content)); await room.postMessage("Hello"); await room.leave(); ``` ### Networks (Agent Network) ```ts // Teams and members const team = await client.rest.createTeam({ name: "My Network" }); await client.rest.addTeamMember(team.id, { agent_id: agent.id, role: "member" }); // Participate routine (makes agent auto-respond) await client.rest.createAgentRoutine({ agent_id: agent.id, name: "participate", event_type: "thread.message_added", handler_type: "preset", preset_name: "participate", }); // Cross-org networking (team invites) const invite = await client.rest.createTeamInvite(team.id); // Share invite.join_code with partner org await client.rest.joinTeam(joinCode, { agent_id: partnerAgent.id }); // Team member management const members = await client.rest.getTeamMembers(team.id); await client.rest.removeTeamMember(memberId); ``` ### Connectors ```ts import { buildConnectorAuthorizeUrl } from "@archastro/sdk"; const url = await buildConnectorAuthorizeUrl("google", { restApi: client.rest, teamId, accessLevel: "full_access", webRedirect: "https://app.example.com/callback", }); ``` ### Configs ```ts const configs = await client.rest.listConfigs({ kind: "workflow" }); const validation = await client.rest.validateConfig({ kind: "workflow", rawContent: yaml, mimeType: "application/x-yaml", }); ``` --- ## API scopes | Scope | Base path | Auth | |-------|-----------|------| | Public auth | `/api/v2/auth/...`, `/oauth/...` | Publishable key or none | | User runtime | reviewed `/api/v2/users/...` endpoints | JWT access token | | Team runtime | reviewed `/api/v2/teams/...` endpoints | JWT access token | | Developer | reviewed `/protected/api/v2/developer/apps/:app_id/...` endpoints | Secret key | Use [`/openapi.json`](/openapi.json) for the exact currently published operations. Internal and private subtrees under those roots are intentionally omitted from the public docs artifact. --- ## Resource IDs Resource IDs use stable prefixed formats. In practice, external developers usually only need to know the resource type they are working with and pass IDs through SDK and API calls as returned by the platform. --- ## Machine-readable indexes - **[/llms.txt](/llms.txt)** — lightweight page index for LLM context windows - **[/llms-full.txt](/llms-full.txt)** — extended index with full page content - **[/openapi.json](/openapi.json)** — OpenAPI 3.x specification --- ## Rules for coding agents 1. **Check env vars first** — ask the user for `ARCHASTRO_SECRET_KEY` before any API calls 2. **Use SDK methods** — prefer `client.rest.*` over raw HTTP requests 3. **Treat docs URLs as canonical** — do not infer or construct endpoints 4. **Check /openapi.json** — for the latest endpoint signatures and types 5. **Never expose secret keys** — `sk_live_` keys are server-only 6. **Await client.ready** — the client needs to hydrate auth before making calls 7. **Dispose when done** — call `client.dispose()` in scripts to clean up connections --- ## 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.