This is the full developer documentation for Ren # Ren documentation > Build, run, and share autonomous agents on managed compute. Get an overview of Ren’s features, integrations, and how to use them. ## See Ren in action [ Tutorials](/docs/tutorials/) [Learn Ren by doing.](/docs/tutorials/) [ Guides](/docs/guides/) [Goal-oriented recipes for every client.](/docs/guides/) [ Deep dives](/docs/deep-dives/) [Understand pods, agents, and the model.](/docs/deep-dives/) [ Developers](/docs/developers/) [API, CLI, and client lookups.](/docs/developers/) # Deep dives > Understand what Ren is, how it works, and why it's built this way. Explanations give you the background and context behind Ren: the ideas, the architecture, and the trade-offs. They’re for understanding, not step-by-step doing; for that, see the [how-to guides](/docs/guides/). [ What is Ren? / Why Ren](/docs/why-ren/) [The technical challenges of becoming AI-native.](/docs/why-ren/) [ How Ren works](/docs/deep-dives/how-ren-works/) [Pods, sandboxes, and managed compute.](/docs/deep-dives/how-ren-works/) [ Concepts](/docs/deep-dives/concepts/compute/) [The platform primitives, grouped.](/docs/deep-dives/concepts/compute/) [ How Ren compares](/docs/why-ren/) [Ren versus the alternatives.](/docs/why-ren/) # Agents > What agents are and the capabilities they compose. Agents are the central primitive in Ren: versioned, configurable definitions that run autonomous reasoning loops. But agents don’t work alone. They compose [skills](/docs/deep-dives/concepts/agents/skills/) for on-demand capabilities, [MCPs](/docs/deep-dives/concepts/agents/mcps/) for external tool access, and [cron triggers](/docs/deep-dives/concepts/agents/cron-triggers/) for scheduled execution. Together, these form the capability stack that defines what an agent can do. [ Agents](/docs/deep-dives/concepts/agents/agents/) [Versioned definitions that run.](/docs/deep-dives/concepts/agents/agents/) [ Skills](/docs/deep-dives/concepts/agents/skills/) [Reusable capabilities agents compose.](/docs/deep-dives/concepts/agents/skills/) [ MCPs](/docs/deep-dives/concepts/agents/mcps/) [External tools via Model Context Protocol.](/docs/deep-dives/concepts/agents/mcps/) [ Cron triggers](/docs/deep-dives/concepts/agents/cron-triggers/) [Run agents on a schedule.](/docs/deep-dives/concepts/agents/cron-triggers/) # Agents > Versioned definitions that Ren runs. An **agent** is a versioned, reusable template that defines everything Ren needs to run an autonomous reasoning loop: a system prompt, a model, a set of skills, MCP servers, permissions, and memory configuration. Agents are the central primitive you configure; Ren handles the execution. ## [Templates, not instances](#templates-not-instances) Agents are templates. They live in the registry, independent of any particular [project](/docs/deep-dives/concepts/compute/projects/). When you add an agent to a project, Ren instantiates that template (wiring in the project’s context, stores, and triggers) without mutating the original definition. This separation means the same agent can run across many projects, each with its own state and sessions, while the agent definition stays single-source-of-truth. ## [What makes up an agent](#what-makes-up-an-agent) Every agent version carries its own complete configuration: * **System prompt**: the instructions that shape the agent’s behavior. * **Model**: which LLM the agent reasons through. * **Skills**: capabilities the agent can invoke on demand. See [Skills](/docs/deep-dives/concepts/agents/skills/). * **MCPs**: external tool servers the agent can call. See [MCPs](/docs/deep-dives/concepts/agents/mcps/). * **Permissions**: what the agent is allowed to do: file access, shell, network, and more. See [Permissions](/docs/deep-dives/concepts/sharing/permissions/). * **Memory**: how the agent recalls information across [sessions](/docs/deep-dives/concepts/agents/sessions/). Because each version is self-contained, upgrading a model or swapping a skill never affects projects pinned to an older version. ## [Agent versions](#agent-versions) Agent versions follow semver: **major.minor.patch**. Creating a new version snapshots the full configuration at that point in time: prompt, model, skills, MCPs, permissions, memory. Projects can either **pin** to a specific version or **track latest**. Pinning gives you stability and reproducibility; tracking latest means you automatically pick up improvements but accept the risk of behavioral changes. This versioning model is why an agent can evolve without breaking existing deployments: old versions continue to work exactly as they did when created, and new versions are opt-in. ## [Primary vs. sub-agents](#primary-vs-sub-agents) Within a project, agents play one of two roles: * **Primary agent**: the entry point for sessions. When a user or trigger starts a session, it goes to the primary agent. Every project has exactly one primary. * **Sub-agent**: a specialist that the primary agent delegates to. Sub-agents have their own prompts, models, and capabilities, but they’re invoked by the primary, not directly by you. This delegation pattern lets you compose complex workflows from focused, well-scoped agents. A primary might handle triage and routing, then hand off to a sub-agent for code review, another for documentation, and a third for deployment, each with the right model and skills for its job. ## [Agents vs. skills](#agents-vs-skills) Agents and skills are complementary but fundamentally different: | | Agent | Skill | | ---------------- | -------------------------------------------------- | ----------------------------------------- | | Reasoning loop | Owns its own loop: thinks, acts, observes, repeats | No loop. Invoked once, returns a result | | State | Stateful across turns within a session | Stateless (no memory between invocations) | | System prompt | | | | Model selection | | | | Can be scheduled | | | | Invoked by | User, trigger, or another agent | An agent | | Analogy | A team member with a role | A tool on that team member's belt | Agent * Reasoning loop Owns its own loop: thinks, acts, observes, repeats * State Stateful across turns within a session * System prompt * Model selection * Can be scheduled * Invoked by User, trigger, or another agent * Analogy A team member with a role Skill * Reasoning loop No loop. Invoked once, returns a result * State Stateless (no memory between invocations) * System prompt * Model selection * Can be scheduled * Invoked by An agent * Analogy A tool on that team member's belt Think of it this way: an agent is someone you hire to do a job. Skills are the tools you give them. The agent decides *when* and *how* to use each tool; the tool just does what it’s told. ## [Publishing and forking](#publishing-and-forking) You can publish an agent to the [registry](/docs/deep-dives/concepts/sharing/registry/) for anyone to discover and install. Publishing is one-way. You can deprecate a published agent but not unpublish it, so projects depending on it always find it. Installing a published agent creates a **fork**: your own editable copy, with its lineage preserved so you can compare against upstream updates. ## [Discovering and creating agents](#discovering-and-creating-agents) ```bash ren agents create --name "Release Notes" --icon "🤖" # create an agent ren models list # list available model ids ren agents versions create \ --prompt "You are a release-notes writer." --model # add a version ren agents search # find published agents ren agents list # list your agents ``` # Cron triggers > Scheduled triggers that fire agents automatically. Agents on Ren normally run when a human sends a message or when an external event arrives. But some work is predictable (a weekly status digest, a nightly code review, a daily Slack summary) and doesn’t need a person to kick it off. **Cron triggers** let you schedule an [agent](/docs/deep-dives/concepts/agents/agents/) session on a recurring timetable, defined by a standard cron expression. ## [How cron triggers work](#how-cron-triggers-work) A cron trigger ties together four things: * **Which agent** to run, within a [project](/docs/deep-dives/concepts/compute/projects/). * **What to say**: the message that seeds the session, just as if you’d typed it. * **When to fire**: a cron expression and an optional timezone. * **Who sent it**: an author, so the triggered session has clear permissions and an audit trail. When the expression next matches the current time, Ren creates a session with that message. The agent runs to completion, and the next firing waits for the following match. ## [Cron expression syntax](#cron-expression-syntax) Cron triggers use the standard five-field cron format: ```plaintext minute hour day-of-month month day-of-week ``` | Field | Allowed values | | ------------ | --------------------- | | Minute | 0 to 59 | | Hour | 0 to 23 | | Day of month | 1 to 31 | | Month | 1 to 12 or JAN to DEC | | Day of week | 0 to 6 or SUN to SAT | Some common patterns: * `0 9 * * MON`: every Monday at 09:00 * `0 0 * * *`: midnight every day * `30 8 1 * *`: 08:30 on the first of every month * `0 */6 * * *`: every six hours The `timezone` field determines which clock the expression is evaluated against. If you set it to `America/New_York`, `0 9 * * MON` fires at 9 AM Eastern, even when daylight saving shifts the UTC offset. ## [Lifecycle](#lifecycle) Scheduling is durable: if the platform has a brief outage, missed firings are retried rather than dropped silently. * **Enabled**: the trigger fires on its schedule. * **Disabled**: firing pauses, but the configuration is kept so you can re-enable it later. * **Archived**: the trigger is removed and no further sessions are created. Changes to the schedule or timezone take effect right away; editing the message applies on the next firing. ## [Cron triggers vs. running agents on demand](#cron-triggers-vs-running-agents-on-demand) Running an agent on demand (through the UI, the CLI, or the API) is the right choice when the work is ad-hoc or user-initiated. Cron triggers fill a different niche: * **Recurring, unattended work.** The agent runs whether or not anyone is online. * **Consistent timing.** The schedule is deterministic; the session fires at the same wall-clock time every cycle. * **Decoupled from human action.** No one needs to remember to start the session. The trade-off is that cron triggers are inherently less flexible than on-demand runs. If the schedule or input needs to change, you must update the trigger itself. You can’t improvise at firing time. ## [What you can do with cron triggers](#what-you-can-do-with-cron-triggers) Common patterns include: * **Periodic digests**: an agent that reads recent activity and posts a summary to Slack every Monday morning. * **Automated reviews**: an agent that reviews pull requests opened in the last 24 hours each night. * **Data pipelines**: an agent that fetches external data, transforms it, and writes results on a fixed cadence. * **Health checks**: an agent that probes an internal service and alerts on failures, running every few minutes. For the step-by-step process of creating and managing cron triggers, see the [schedule a cron trigger](/docs/guides/automate/schedule-cron-trigger/) guide. # MCPs > Attaching external tools to agents via the Model Context Protocol. An **MCP** (Model Context Protocol server) is Ren’s primitive for giving an [agent](/docs/deep-dives/concepts/agents/agents/) access to external tools and services. Where a [skill](/docs/deep-dives/concepts/agents/skills/) teaches an agent *how* to do something, an MCP gives it *something to reach out to*: an API, a database, a search engine, or any service that speaks the MCP protocol. ## [Remote vs. local](#remote-vs-local) MCPs come in two flavors, depending on where the server runs: **Remote MCPs** are hosted somewhere on the internet: your infrastructure, a vendor’s API, or a shared service. You give Ren a URL, and the agent connects to it at runtime. This is the common case for third-party services (Slack, GitHub, databases) and for any server you already host. **Local MCPs** run inside Ren’s sandbox. Instead of a URL, you provide a command (for example, `npx @example/mcp`) and Ren spins up the process on demand. Local MCPs are useful for tools that don’t have a hosted version, or when you want the server to run in the same environment as the agent. The choice between remote and local is mostly about where the server lives. The agent doesn’t care. It calls tools the same way regardless. ## [Transport protocols](#transport-protocols) When an agent connects to an MCP server, it uses one of three transports: * **Streamable HTTP** (default): the modern MCP transport. A single HTTP endpoint that supports both request-response and streaming. Use this unless you have a reason not to. * **SSE**: server-sent events over HTTP. The original MCP transport, still supported for backward compatibility with older servers. * **Stdio**: standard input/output, used exclusively by local MCPs. Ren pipes messages to and from the spawned process. For remote MCPs, streamable HTTP is the sensible default. For local MCPs, stdio is the only option and is chosen automatically. ## [Authentication](#authentication) An MCP server may require authentication before the agent can use it. Ren supports four auth types: * **None** (default): no credentials needed. The server is open or uses IP-based allowlisting. * **API key**: a static key sent as a header or query parameter. You configure which header or parameter name the server expects, including the `Authorization` header for bearer-style tokens. Simple and common for SaaS APIs. * **Basic**: HTTP Basic authentication (username and password), for services that still require it. * **OAuth**: the full OAuth 2.0 flow. You configure scopes, token endpoints, and authorization endpoints. Ren handles the redirect and token exchange at runtime. Used for services that require user-delegated access (e.g., “act on behalf of this Slack user”). ### [Credentials and vaults](#credentials-and-vaults) Credentials are **not** stored on the MCP definition. Instead, an MCP declares the credential slots it needs (a name, description, and auth type). At runtime, Ren fills those slots from a [vault](/docs/deep-dives/concepts/stores/vault/) that holds the actual secret values. This separation means secrets never appear in a definition that may be shared or published, and the same MCP can serve different agents with different credentials: a shared “Slack” MCP can use one team’s token in project A and another’s in project B. ## [How MCPs attach to agents](#how-mcps-attach-to-agents) MCPs are attached to an [agent](/docs/deep-dives/concepts/agents/agents/) **version**, so each version can have a different set of tools. You might add a new server in v2 without touching v1. When an agent starts a session, Ren collects its MCPs, fills their credentials from the vault, and presents the available tools to the model. The agent decides which to call, just as it decides which [skills](/docs/deep-dives/concepts/agents/skills/) to invoke. ## [Scopes and sharing](#scopes-and-sharing) Like agents and skills, MCPs have a [scope](/docs/deep-dives/concepts/sharing/scopes/): * **Private**: only visible to you. * **Org**: visible to everyone in your organization, for shared infrastructure like a company-wide database MCP. * **Public**: published to the [registry](/docs/deep-dives/concepts/sharing/registry/) for anyone to install. Publishing an MCP shares it without revealing credentials. The credential slots travel with the definition, but the secrets stay in each installer’s vault. ## [MCPs vs. skills](#mcps-vs-skills) MCPs and skills both extend what an agent can do, but they operate at different layers: | | MCP | Skill | | ---------------- | ---------------------------------------------- | ---------------------------------------------------- | | What it provides | External tools and services | Instructions and scripts the agent runs locally | | Where it runs | On a remote server or in a sandbox process | Inside the agent's reasoning loop | | Protocol | MCP (tools/resources/prompts) | Ren skill protocol (instructions + optional scripts) | | State | The server owns its own state | Stateless. Invoked once, returns a result | | Auth | May require credentials (API key, OAuth, etc.) | No auth. It's part of the agent | | Analogy | A phone line to an external service | A procedure the agent has memorized | MCP * What it provides External tools and services * Where it runs On a remote server or in a sandbox process * Protocol MCP (tools/resources/prompts) * State The server owns its own state * Auth May require credentials (API key, OAuth, etc.) * Analogy A phone line to an external service Skill * What it provides Instructions and scripts the agent runs locally * Where it runs Inside the agent's reasoning loop * Protocol Ren skill protocol (instructions + optional scripts) * State Stateless. Invoked once, returns a result * Auth No auth. It's part of the agent * Analogy A procedure the agent has memorized The practical distinction: if the capability lives outside Ren and the agent needs to call it over a network, it’s an MCP. If the capability is a set of instructions or a script the agent carries and runs itself, it’s a skill. Many agents use both: skills for reasoning patterns and local actions, MCPs for reaching external systems. ## [Discovering and creating MCPs](#discovering-and-creating-mcps) The Ren CLI provides commands for working with MCPs: * `ren mcps create --name "X" --mcp-server-url "https://..."`: create a remote MCP. * `ren mcps create --name "X" --type local --command "npx @example/mcp"`: create a local MCP. * `ren mcps list`: view the MCPs available to you. * `ren mcps search`: find published MCPs in the registry. For the full walkthrough of registering an MCP and wiring it to an agent, see [Connect an MCP server](/docs/guides/build-and-run/create-a-custom-mcp/). # Sessions > Multiplayer agent runs with replays, mentions, and inline auth. A **session** is the atomic unit of work in Ren: a single conversation or task execution between one or more humans and one or more agents. Everything you do on the platform, from a quick question to a multi-day project, lives inside a session. Unlike a single-player chat thread, every session is multiplayer from the start, fully recorded, and shareable. A teammate can review an agent’s output mid-stream, a second agent can take a subtask, and anyone can catch up later. You never have to “upgrade” a private chat into a shared one. ## [How sessions work](#how-sessions-work) ### [Turn-based attribution](#turn-based-attribution) Every message in a session is attributed to its sender: a specific human or a specific [agent](/docs/deep-dives/concepts/agents/agents/). There is no anonymous “the AI said” bucket. When three people and two agents are in the same session, you can always see who said what, who ran which tool, and who approved which action. This matters for accountability and for context. When an agent reads back through a session to decide what to do next, it sees the same attributed history everyone else sees: no information asymmetry. ### [Session lifecycle](#session-lifecycle) A session moves through four statuses: | Status | Meaning | | ----------- | ------------------------------------------------------------ | | **idle** | No agent is currently working. Waiting for human input. | | **busy** | An agent is actively processing or running a tool. | | **waiting** | An agent has paused and needs human input to continue. | | **error** | Something went wrong. The agent stopped and needs attention. | Most sessions spend their time cycling between **idle** and **busy**. The **waiting** status is intentional. It is how an agent signals that it cannot proceed without a human decision, not a failure state. ### [Where sessions live](#where-sessions-live) Every session belongs to a [project](/docs/deep-dives/concepts/compute/projects/) and runs inside a [pod](/docs/deep-dives/concepts/compute/pods/). The project scopes permissions and data; the pod provides the compute environment where the agent actually executes. Switching the pod or project mid-session is not supported. If you need a different environment, start a new session. ## [Multiplayer by default](#multiplayer-by-default) Anyone in the same [project](/docs/deep-dives/concepts/compute/projects/) can join a session. There’s no invite step and no private mode. Updates flow to every participant in real time: when an agent produces output, everyone sees it immediately; when someone types a message, the agent sees it on the next turn. ### [Switching agents mid-session](#switching-agents-mid-session) Sessions are not locked to a single agent. The **agent selector** lets you switch which agent handles the conversation at any point. This is useful when a task changes shape: for example, starting with a general-purpose agent for exploration, then switching to a specialized code-review agent for the final pass. Switching agents does not erase history. The new agent reads the full session transcript and continues from where the previous one left off. ## [Use @-mentions and context injection](#use--mentions-and-context-injection) Typing `@` in the message composer opens a context menu with four mention types: * **@agent**: Pull another agent into the session. The mentioned agent receives the conversation context and can respond in-thread. * **@file**: Attach a file from the project. The agent reads the file content directly, no copy-paste needed. * **@user**: Notify a teammate. They get a push notification and can jump into the session. * **@memory**: Reference a stored memory or note. The agent loads the referenced context without re-deriving it from scratch. Each mention type injects different context into the session. This is how you give an agent exactly the information it needs without cluttering the prompt with everything. ## [Inline authentication](#inline-authentication) When an agent needs access to an external service (an API key, an OAuth token, a database credential), it does not ask you to paste secrets into the chat. Instead, the session surfaces an **inline auth prompt**: a button embedded directly in the conversation. The prompt appears in yellow when credentials are needed and turns green once connected. Behind the scenes, the credentials are stored in a [vault](/docs/deep-dives/concepts/stores/vault/): an encrypted secret store scoped to the project. The agent never sees the raw credential; it receives a short-lived token or session that the vault manages. This pattern keeps secrets out of chat history, out of agent memory, and out of session replays. ## [Replays](#replays) Every session is recorded from start to finish. A **replay** is a shareable link that lets anyone, even people outside your project, watch the session unfold message by message, exactly as it happened. You control who can view by distributing the link. There’s no separate permission grant. This makes it easy to share a debugging session with a vendor, walk a teammate through a decision trail, or demo a workflow to a stakeholder. Replays are read-only. Viewers cannot resume the session or inject messages. They watch the history as it was recorded. ## [Tasks and todos](#tasks-and-todos) Inside a session, agents can create and track **todos**, lightweight task items with a status lifecycle: * **pending**: Created but not yet started. * **in\_progress**: The agent is actively working on it. * **completed**: Done. * **cancelled**: Intentionally dropped. Todos give you a running checklist of what the agent is doing, which is especially useful in long sessions where the agent is working through a multi-step plan. You can see at a glance what has been finished and what is still in progress, without reading every message. ## [Subagent sessions](#subagent-sessions) When an agent delegates work to another agent, it creates a **subagent session**: a child of the parent session. The subagent runs independently, and its results flow back into the parent when it finishes. This keeps the main conversation clean. You do not see the subagent’s internal tool calls and reasoning cluttering your thread; you see the outcome. If you need to dig deeper, you can navigate into the subagent session from the parent. ## [Creating sessions](#creating-sessions) Sessions can originate from several entry points: * **The Ren UI**: Click into a project and start a new session. Pick an agent, type a message, go. * **Integrations**: A Slack message, a GitHub event, or another integration can create a session automatically. * **Programmatic**: The API and CLI both support session creation for scripted workflows. From the CLI: ```bash ren sessions create --pod-id --project-id --title "Investigate flaky test" ren sessions list ``` Regardless of how a session is created, it behaves the same way: multiplayer, recorded, and attributed. # Skills > Reusable capabilities that agents compose. A **Ren skill** is a reusable, versioned capability an [agent](/docs/deep-dives/concepts/agents/agents/) can invoke: a discrete ability like “summarize a document,” “query a CRM,” or “run a security scan.” ## [Ren skills vs. agent commands](#ren-skills-vs-agent-commands) A coding agent like Claude Code or opencode may have its own slash commands or skills: local shortcuts defined in a config file, with no versioning, sharing, or credential management. A **Ren skill** is different: it lives on the server, is versioned independently, can be shared across agents and organizations, and declares the credentials it needs. In these docs, “skill” always means the Ren primitive. ## [What a skill contains](#what-a-skill-contains) Every skill bundles three things: 1. **Interface**: the inputs it accepts and outputs it produces, so an agent knows what to pass and what to expect. 2. **Instructions**: the prose or code that runs when the skill is invoked. 3. **Required credentials**: the secrets it needs at runtime, supplied from a [vault](/docs/deep-dives/concepts/stores/vault/) so the skill never handles raw secrets. ### [The SKILL.md manifest](#the-skillmd-manifest) Every skill has a `SKILL.md` file at its root. Its frontmatter declares: * **`name`**: a hyphen-case identifier, 1 to 64 characters (e.g. `search-crm`). * **`description`**: a human-readable summary. * **`license`** *(optional)*: the license the skill is published under. * **`allowed-tools`** *(optional)*: tools the skill is permitted to use. The body holds the skill’s instructions: the guidance the agent follows while the skill runs. ## [Versions](#versions) Skills use **semver**, starting at `0.0.1`. Each version carries its own source files, supplied either as an uploaded archive or as a reference into a Git repository (a repo URL, optional ref, and optional sub-path). When an [agent](/docs/deep-dives/concepts/agents/agents/) attaches a skill, it can pin a specific version or track the latest. Pinning gives stability; tracking latest means updates apply automatically. Choose based on how sensitive the workflow is to changes. ## [Required credentials](#required-credentials) A skill declares the secrets it needs as named slots (for example `SALESFORCE_API_KEY`), each with an optional description. These are a contract, not the secret itself. When you attach the skill to an agent, Ren checks the agent’s [vault](/docs/deep-dives/concepts/stores/vault/) for every declared credential and fails fast with a clear message if any are missing. ## [Scopes and publishing](#scopes-and-publishing) A skill has a [scope](/docs/deep-dives/concepts/sharing/scopes/): **private** (just you), **org** (your organization), or **public** (the [registry](/docs/deep-dives/concepts/sharing/registry/)). Publishing is one-way: a public skill can’t be unpublished, only deprecated, because other agents may depend on it. ## [Skills, agents, and MCPs](#skills-agents-and-mcps) | | Skill | Agent | MCP | | -------------- | ------------------- | ---------------------------- | ------------------------- | | Role | What the agent does | Who reasons and orchestrates | What the agent can access | | Reasoning loop | | | | | System prompt | | | | | Stateful | | | | | Invoked by | An agent | A user or trigger | An agent (tool call) | | Schedulable | | | | Skill * Role What the agent does * Reasoning loop * System prompt * Stateful * Invoked by An agent * Schedulable Agent * Role Who reasons and orchestrates * Reasoning loop * System prompt * Stateful * Invoked by A user or trigger * Schedulable MCP * Role What the agent can access * Reasoning loop * System prompt * Stateful * Invoked by An agent (tool call) * Schedulable An **agent** decides what to do. **Skills** are the actions it can take: self-contained procedures it carries and runs. **MCPs** are the external services it can reach. An agent might use a skill to “draft a pull request” and an MCP to “read from GitHub”: the skill provides the procedure, the MCP provides the access. ## [CLI commands](#cli-commands) ```bash ren skills create ./my-skill --name "My skill" # upload a folder containing SKILL.md ren skills versions create ./my-skill # add a version from a folder ren skills search # search the registry ren skills list # list skills visible to you ``` For the full reference, see the [CLI docs](/docs/developers/cli/). For a walkthrough, see [Create a skill](/docs/guides/build-and-run/create-a-skill/). # Compute > Where agents live and run (pods, projects, and environments). Agents need a place to run, configuration to shape their behavior, and isolation boundaries to keep workloads separate. Ren’s compute model is built around three primitives: [pods](/docs/deep-dives/concepts/compute/pods/) provide the runtime environment, [projects](/docs/deep-dives/concepts/compute/projects/) group related agents and resources, and [environments](/docs/deep-dives/concepts/compute/environments/) configure how pods are provisioned. [ Pods](/docs/deep-dives/concepts/compute/pods/) [The top-level workspace where agents execute.](/docs/deep-dives/concepts/compute/pods/) [ Projects](/docs/deep-dives/concepts/compute/projects/) [Groups of agents, skills, and stores.](/docs/deep-dives/concepts/compute/projects/) [ Environments](/docs/deep-dives/concepts/compute/environments/) [Configuration and isolation boundaries.](/docs/deep-dives/concepts/compute/environments/) # Environments > Configuration and isolation boundaries for running agents. ## [What environments are for](#what-environments-are-for) When an agent moves from a developer’s laptop to a staging review and finally into production, the surrounding configuration should change with it: different credentials, different network rules, different pre-installed packages. An **environment** is the Ren primitive that captures those differences. Each environment is a named, versionable configuration record that a [pod](/docs/deep-dives/concepts/compute/pods/) can point to. When a pod references an environment, that environment’s settings are applied to the sandbox the pod runs in: from which hosts the agent may contact, to which system packages are installed before the agent starts. ## [How environments relate to pods and projects](#how-environments-relate-to-pods-and-projects) A [pod](/docs/deep-dives/concepts/compute/pods/) can point to an environment; its sandbox is then bootstrapped with that environment’s networking rules and packages. Without one, a pod runs with unrestricted networking and no extra packages. A [project](/docs/deep-dives/concepts/compute/projects/) inherits its pod’s environment. One environment can be shared across many pods (every staging pod might point to the same “staging” environment), or each pod can carry its own. ## [What an environment controls](#what-an-environment-controls) ### [Networking](#networking) An environment has two networking modes: * **Unrestricted**: the sandbox can reach any host. Fine for development or trusted internal workloads. * **Limited**: outbound access is gated by three controls: * Whether the sandbox may connect to MCP servers. * Whether it may reach package registries (npm, PyPI, crates.io, etc.). * An explicit allow-list of hostnames it may contact. Limited networking is the foundation for production isolation: an agent that should only talk to your internal API and your MCP servers can be locked down so it can’t exfiltrate data to an arbitrary endpoint. ### [Packages](#packages) An environment can pre-install system and language packages into the sandbox before the agent starts, so the first run already has the tools it needs. Each package manager takes a list of package names: | Key | Package manager | Example | | ------- | ------------------- | -------------------------- | | `apt` | APT (Debian/Ubuntu) | `curl`, `git` | | `npm` | npm (global) | `typescript`, `prettier` | | `pip` | pip (user install) | `requests`, `black` | | `cargo` | Cargo (Rust) | `ripgrep`, `fd-find` | | `gem` | RubyGems | `rubocop` | | `go` | Go install | `golang.org/x/tools/gopls` | Environments run on Ren-managed cloud infrastructure. ## [Scoping resources per stage](#scoping-resources-per-stage) An environment also acts as a boundary for resources that should differ across deployment stages: * **Credentials**: scope a secret to an environment so a production agent never uses a development API key. * **Agent versions**: pin different versions per environment for safe promotion from staging to production. * **File stores**: keep production data separate from development artifacts. A pod bound to an environment can only access resources that match that environment (or are environment-agnostic). ## [Lifecycle](#lifecycle) * **Create**: define a name, networking, and optional packages. * **Update**: change networking or packages at any time; pods pick up the change on their next sync. * **Archive**: remove it from new-pod selection. Pods already using it keep running on their last-known-good configuration. ## [Current state](#current-state) Environments are under active development. Networking and packages are available today; detailed guides for common patterns (e.g. “lock down a production agent”) are still being written. # Pods > The top-level workspace that contains everything else. A **pod** is the compute environment where an [agent](/docs/deep-dives/concepts/agents/agents/) runs. It pairs two things: * A **server**: a persistent process that holds state and stays reachable between tasks. * A **sandbox**: an isolated environment where code actually runs, with its own filesystem, CPU, and network boundary. The pod fuses both into one managed unit, so the agent has a place to *be* (the server) and a place to *do* (the sandbox) without you wiring them together. ## [Isolation](#isolation) A pod is an isolation boundary. Each pod has its own compute, its own attached [vaults](/docs/deep-dives/concepts/stores/vault/), and its own member list. Agents in different pods can’t see each other’s files, processes, or secrets. ## [Pods and projects](#pods-and-projects) A pod runs one or more [projects](/docs/deep-dives/concepts/compute/projects/), and every project belongs to exactly one pod. Projects on the same pod share its server, sandbox, and network, so they coordinate cheaply while staying logically distinct. Most projects are lightweight and don’t need a dedicated pod. Give a heavy workload its own pod when you want to isolate it from everything else. ## [Default pods](#default-pods) * Every user gets a **private pod** automatically: yours alone, no setup required. * Every organization gets a pod named **general**. Teammates you add get access to its projects and agents with no extra configuration. It comes with a default project and a default vault already attached. You can create more pods whenever you need a new isolation boundary. ## [Membership](#membership) Pods are shared through two roles: * **Owner**: can manage the pod’s configuration, members, and attached resources. * **Member**: can use the pod’s compute and access its projects, but can’t change the pod itself. This is deliberately coarse. A pod is an infrastructure boundary; fine-grained access control over agents and data is handled at the [project](/docs/deep-dives/concepts/compute/projects/) level. ## [Vaults](#vaults) Vaults attach to a pod with a **priority**. When the same credential exists in more than one attached vault, the higher-priority vault wins, so a team vault can override org-level defaults for specific keys without replacing the org vault. Every pod gets a default vault at creation, so agents always have somewhere to store and retrieve secrets. See [Vault](/docs/deep-dives/concepts/stores/vault/). ## [Where to go next](#where-to-go-next) * [Projects](/docs/deep-dives/concepts/compute/projects/): how agents, skills, and stores are grouped inside a pod. * [Environments](/docs/deep-dives/concepts/compute/environments/): networking and package configuration for a pod’s sandbox. * [Agents](/docs/deep-dives/concepts/agents/agents/): what actually runs inside a pod. # Projects > How agents, skills, and stores are grouped inside a pod. A **project** is the organizational unit that ties agents, file stores, memory stores, and permissions together into a single deployable context. If a [pod](/docs/deep-dives/concepts/compute/pods/) is the machine where agents run, a project is one *piece of work* on that machine: the specific set of agents, data, and rules that belong together. A pull-request reviewer needs a Git repo, a working file store, and a memory of past reviews; a Slack triager needs different stores and a different permission profile. A project collects those bindings (which agents work together, which stores they share, what they’re allowed to do) once, so every session inherits the full context. This matters most when a primary agent delegates to subagents that all need the same repo and memory. ## [Where a project lives](#where-a-project-lives) Every project belongs to exactly one [pod](/docs/deep-dives/concepts/compute/pods/). The pod provides the compute, filesystem, and network; the project defines *what runs inside it* and *what it has access to*. A pod can hold multiple projects, each with its own agents, stores, and permissions, sharing the same sandbox. Each project gets its own root directory in the sandbox, which is the working directory agents see when a session starts. ## [Agents and their roles](#agents-and-their-roles) A project assigns each [agent](/docs/deep-dives/concepts/agents/agents/) a role: * **Primary**: the entry point. A new session goes to the primary agent, which handles the task or delegates to a subagent. * **Subagent**: a specialist the primary delegates to. Subagents don’t receive session messages directly; the primary invokes them when needed. * **All**: acts as both, for simple projects where one agent does everything. A project needs at least one primary agent to run. The primary-subagent split is what enables [multi-agent coordination](/docs/deep-dives/concepts/agents/agents/): the primary routes, subagents provide depth. ## [Stores: files and memory](#stores-files-and-memory) A project attaches [file stores](/docs/deep-dives/concepts/stores/file-stores/) for persistent artifacts (code, documents, config) and [memory stores](/docs/deep-dives/concepts/stores/memory-stores/) for long-term recall. A store can be shared across projects, and a project can mount several. Attaching stores at the project level means every agent in the project sees the same data. A primary agent writes a plan to a file store, and its subagents read it. ## [Git repositories](#git-repositories) A project can bind a GitHub repository: the repo URL, an optional base branch, and an optional path to clone into. When a session opens, Ren clones the repo into the sandbox, giving agents a real working tree to read, edit, run tests against, and open pull requests from. ## [Permissions](#permissions) Each project has a [permission policy](/docs/deep-dives/concepts/sharing/permissions/) that controls what agents in it are allowed to do: file reads, shell commands, web access, and so on. Because permissions are scoped to the project, the same agent can have read-only access in one project and full write access in another. ## [The CLI surface](#the-cli-surface) Projects are managed through the Ren CLI: ```bash # Create a project inside a pod ren projects create --pod-id --name "My Project" # List projects ren projects list # Attach an agent to a project ren projects agents add --agent-id --type primary # Attach a file store ren projects file-stores add --file-store-id # Attach a memory store ren projects memory-stores add --memory-store-id ``` ## [How it fits together](#how-it-fits-together) An org owns pods, pods contain projects, and projects bind agents and stores. Within a project everything is a first-class attachment, not a nested child, so you can reuse the same agent across projects, share a file store between projects in a pod, and reassign agents without rebuilding anything. The project is where reusable definitions (agents, skills, stores) meet a concrete deployment (a pod, a repo, a permission policy). # Sharing > How work is shared and access is controlled. Ren’s sharing and governance model controls who can see resources, who can modify them, and what agents are allowed to do. These concepts work together: [scopes](/docs/deep-dives/concepts/sharing/scopes/) determine visibility, the [registry](/docs/deep-dives/concepts/sharing/registry/) enables discovery, and [permissions](/docs/deep-dives/concepts/sharing/permissions/) gate what agents can do at runtime. [ Registry](/docs/deep-dives/concepts/sharing/registry/) [Publish and discover agents, skills, MCPs, and blueprints.](/docs/deep-dives/concepts/sharing/registry/) [ Blueprints](/docs/deep-dives/concepts/sharing/blueprints/) [Packaged, reusable setups.](/docs/deep-dives/concepts/sharing/blueprints/) [ Scopes](/docs/deep-dives/concepts/sharing/scopes/) [Visibility and access boundaries: private, org, and registry.](/docs/deep-dives/concepts/sharing/scopes/) [ Permissions](/docs/deep-dives/concepts/sharing/permissions/) [Capability-based access control for agent actions.](/docs/deep-dives/concepts/sharing/permissions/) # Blueprints > Packaged, reusable setups you can install. A **blueprint** is a complete Ren setup packaged as one installable unit. It captures [agents](/docs/deep-dives/concepts/agents/agents/), [skills](/docs/deep-dives/concepts/agents/skills/), MCPs, projects, triggers, and the wiring between them: everything someone needs to reproduce a working setup in their own organization. Instead of recreating an agent, attaching its skills and MCPs, and configuring projects by hand, you install a blueprint and let it do the wiring. ## [What a blueprint contains](#what-a-blueprint-contains) A blueprint declares the resources that should exist and how they connect: * **Projects**: name, permissions, bound agents, and cron triggers. * **Agents**: at a specific version, with their prompt, model, skills, MCPs, and permissions. * **Skills** and **MCPs**: the capabilities the agents use. * **Replays**: recorded sessions that show how the setup is used. ## [How installation works](#how-installation-works) When you install a blueprint, Ren handles each resource one of three ways: * **Link**: the resource is already in your organization or published on the [registry](/docs/deep-dives/concepts/sharing/registry/), so Ren references it directly without copying. * **Fork**: the resource isn’t reachable from your org, so Ren copies it into your organization. The copy is independent: changes to the original don’t affect it. * **Skip**: the resource can’t be linked or forked (for example, it was archived). Skips are reported so you can decide how to handle them. Installation is all-or-nothing: if any copy fails, the whole install rolls back. You never end up with a half-installed blueprint. ## [Publishing](#publishing) Before others can install a blueprint, you publish it. Publishing also publishes every resource it references (agents, skills, MCPs, and replays), so the blueprint is never missing a dependency. Publishing again is a no-op. ## [Visibility](#visibility) Blueprints follow the same [scopes](/docs/deep-dives/concepts/sharing/scopes/) as other resources: **private**, **org**, or **public** (registry). The scope of each resource inside a blueprint decides whether installers link it (public/shared) or fork it (private/cross-org). ## [Discovering and installing](#discovering-and-installing) You browse published blueprints in the [registry](/docs/deep-dives/concepts/sharing/registry/) and install one by slug or ID. The install process links what it can, forks what it must, and reports anything it skipped. Note Unlike agents, skills, and MCPs, blueprints don’t have dedicated CLI commands yet. Install a blueprint through the API. See [Build and install a blueprint](/docs/guides/share/build-install-blueprint/) for the request shape. # Permissions > How Ren decides what an agent is allowed to do. Every time an [agent](/docs/deep-dives/concepts/agents/agents/) takes an action (reading a file, running a shell command, calling an MCP tool), Ren checks a permission first. Permissions are capability-based: instead of roles like “admin” or “viewer”, you allow, deny, or require approval for each specific capability. A code-review agent might get `read` and `grep` but not `bash`; a deploy agent might get `bash` and `edit` but not `webfetch`. ## [Permission values](#permission-values) Every capability resolves to one of three values: | Value | Meaning | | ------- | --------------------------------------------------- | | `allow` | The agent may perform the action without prompting. | | `deny` | The action is blocked. | | `ask` | The agent must get human approval first. | You can set a single value for everything, or set values per capability. ## [Capability keys](#capability-keys) | Key | What it gates | | -------------------- | --------------------------------------------------------------- | | `read` | Reading file contents. | | `edit` | Writing or modifying files. | | `glob` | Listing files matching a pattern. | | `grep` | Searching file contents. | | `list` | Listing directory contents. | | `bash` | Executing shell commands. | | `task` | Delegating to sub-agents. | | `external_directory` | Accessing paths outside the project root. | | `todowrite` | Updating the agent’s todo list. | | `question` | Asking a clarifying question. | | `webfetch` | Fetching content from a URL. | | `websearch` | Performing web searches. | | `codesearch` | Searching code across repositories. | | `lsp` | Using language-server features (go-to-definition, diagnostics). | | `skill` | Invoking a [skill](/docs/deep-dives/concepts/agents/skills/). | ## [Pattern maps](#pattern-maps) Capabilities like `read`, `edit`, `bash`, `external_directory`, and `skill` accept a **pattern map** instead of a single value: mapping glob-like patterns to actions. For example, allow reading `src/`, deny `.env`, and ask for everything else: ```json { "read": { "src/**": "allow", ".env*": "deny", "*": "ask" } } ``` Patterns are evaluated most-specific first; `"*"` is the catch-all. ## [Project vs. agent permissions](#project-vs-agent-permissions) Permissions are set at two levels: * **Agent permissions** define what an agent needs to function. * **Project permissions** define organizational policy: the ceiling for any agent running in that project. When both apply, the stronger restriction wins: `deny` beats `ask` beats `allow`. So a project-level `bash: deny` can’t be overridden by any agent. Set restrictive defaults at the project level, then let individual agents request the narrower access they need. ## [Where to go next](#where-to-go-next) * [Scopes](/docs/deep-dives/concepts/sharing/scopes/): who can see and reference a resource, the other half of access control. * [Agents](/docs/deep-dives/concepts/agents/agents/): where agent permissions are configured. * [Projects](/docs/deep-dives/concepts/compute/projects/): the project-level permission layer. # Registry > Publish and discover agents, skills, MCPs, and blueprints. The Ren registry is the public catalog where organizations publish reusable [agents](/docs/deep-dives/concepts/agents/agents/), [skills](/docs/deep-dives/concepts/agents/skills/), [MCPs](/docs/deep-dives/concepts/agents/mcps/), and [blueprints](/docs/deep-dives/concepts/sharing/blueprints/) for anyone to discover and install. It’s how a capability moves from a single organization to shared infrastructure. It’s a publishing system, not a marketplace: no ratings or reviews. Organizations publish what they build; others find it by slug and install it. ## [Publishers](#publishers) Every published resource is attributed to a **publisher**: your organization’s namespace on the registry, with a unique slug (e.g. `acme-corp`) that prefixes everything you publish. There’s one publisher per organization, created automatically the first time you publish. ## [Publishing](#publishing) Publishing makes a resource public and discoverable. When you publish an agent, Ren first publishes everything it depends on (the skills and MCPs on its latest version), so a published resource never has a missing dependency. Publishing a [blueprint](/docs/deep-dives/concepts/sharing/blueprints/) works the same way for the agents, skills, MCPs, and replays it references. ## [Deprecation, not deletion](#deprecation-not-deletion) Published resources can’t be unpublished. Projects depending on them would break. Instead you **deprecate**: the resource drops out of registry search but stays reachable by direct slug or ID, so existing installs keep working. A deprecation message can point users to a replacement. Deprecation is reversible. ## [Discovering](#discovering) Browse published resources from the CLI, one type at a time: ```bash ren registries agents list # browse published agents ren registries skills list # browse published skills ren registries mcps list # browse published MCPs ren publishers me # show your organization's publisher ``` ## [Where to go next](#where-to-go-next) * [Scopes](/docs/deep-dives/concepts/sharing/scopes/): how publishing changes a resource’s visibility. * [Blueprints](/docs/deep-dives/concepts/sharing/blueprints/): installable setups that bundle agents, skills, and MCPs. * [Agents](/docs/deep-dives/concepts/agents/agents/): the main resource type published to the registry. # Scopes > How Ren determines who can see and reference a resource. Every resource in Ren ([agents](/docs/deep-dives/concepts/agents/agents/), [skills](/docs/deep-dives/concepts/agents/skills/), [MCPs](/docs/deep-dives/concepts/agents/mcps/), [vaults](/docs/deep-dives/concepts/stores/vault/), file stores, memory stores, [projects](/docs/deep-dives/concepts/compute/projects/), [pods](/docs/deep-dives/concepts/compute/pods/), [blueprints](/docs/deep-dives/concepts/sharing/blueprints/)) has a **scope** that controls who can see it and reference it. ## [The three scopes](#the-three-scopes) * **Private**: belongs to one user. Only that user can see or use it. Good for personal experiments and drafts. * **Org**: belongs to the organization. Every member can see and use it. This is the default and the workhorse of team collaboration. * **Registry (public)**: published to the [registry](/docs/deep-dives/concepts/sharing/registry/) and usable by anyone, in any organization. ## [Owning vs. referencing](#owning-vs-referencing) Scope governs two different things: * **Owning**: modifying, archiving, or deleting a resource. You can own org resources in your org and your own private resources, but never another user’s private resources. * **Referencing**: using a resource from your own, like attaching a skill to an agent or installing a blueprint. Anyone can reference a published (registry) resource. Otherwise you can only reference what you could own. ## [Scope can only narrow](#scope-can-only-narrow) References can narrow scope through a dependency graph, never widen it. An org-scoped agent can reference org and registry skills, but not another user’s private skill. This means you can’t make a private resource reachable by attaching it to something more public. If a skill is invisible to your teammates, an org agent can’t bridge access to it. ## [What can be published](#what-can-be-published) | Resource | Default scope | Can be published? | | ------------- | ------------- | ----------------- | | Agents | Org | Yes | | Skills | Org | Yes | | MCPs | Org | Yes | | Blueprints | Org | Yes | | Replays | Org | Yes | | Vaults | Org | No | | File stores | Org | No | | Memory stores | Org | No | | Projects | Org | No | | Pods | Org | No | Secrets, storage, and compute (vaults, stores, projects, pods) can’t be published. They stay private or org-scoped permanently. ## [Where to go next](#where-to-go-next) * [Registry](/docs/deep-dives/concepts/sharing/registry/): how publishing moves a resource from org to public scope. * [Permissions](/docs/deep-dives/concepts/sharing/permissions/): what an agent can do once it can reference a resource. * [Blueprints](/docs/deep-dives/concepts/sharing/blueprints/): packaged setups that install across scopes. # Stores > How agents store secrets, files, and what they remember. Agents need three kinds of persistent data: secrets they must never leak, files they read and write, and memories they carry across sessions. Ren models these as distinct primitives ([vaults](/docs/deep-dives/concepts/stores/vault/) for credentials, [file stores](/docs/deep-dives/concepts/stores/file-stores/) for persisted files, and [memory stores](/docs/deep-dives/concepts/stores/memory-stores/) for cross-session recall), each with its own scoping, encryption, and lifecycle rules. [ Vault](/docs/deep-dives/concepts/stores/vault/) [Secrets and credentials.](/docs/deep-dives/concepts/stores/vault/) [ File stores](/docs/deep-dives/concepts/stores/file-stores/) [Persisted, shareable files.](/docs/deep-dives/concepts/stores/file-stores/) [ Memory stores](/docs/deep-dives/concepts/stores/memory-stores/) [What agents remember across sessions.](/docs/deep-dives/concepts/stores/memory-stores/) # File stores > Persisted, shareable file storage for agents. Agents don’t just think. They produce files. A generated report, a downloaded dataset, a configuration file an agent edited on your behalf. These artifacts need to survive beyond a single session, and they need to be reachable by other agents working on the same project. That’s what file stores are for. ## [What is a file store?](#what-is-a-file-store) A file store is a managed, persistent filesystem attached to a [project](/docs/deep-dives/concepts/compute/projects/). It gives agents a real directory tree they read and write like a local disk, except the contents persist across sessions and can be shared across a team. Each organization and user gets a default file store automatically; additional stores are opt-in. A store can back multiple projects, and a project can mount several, so you share artifacts without duplicating them. ## [How it works in the sandbox](#how-it-works-in-the-sandbox) Inside a [pod](/docs/deep-dives/concepts/compute/pods/), a file store is a real directory mounted into the sandbox. Agents use ordinary file operations (open, read, write, rename, delete) with no special “save” call and no adapter code. Any tool or library that expects a filesystem just works. Changes are picked up on the next run, so the agent never sees stale data. ## [Persistence across sessions](#persistence-across-sessions) The defining property of a file store is durability. Files an agent writes during one session are available the next time that agent, or any other agent with access to the same store, runs. This is what separates a file store from ephemeral sandbox storage, which vanishes when the pod shuts down. Persistence makes it practical for agents to: * **Accumulate knowledge**: an agent can write a findings file in one run and append to it in the next. * **Hand off work**: one agent produces a data file; another agent in a different session picks it up and processes it further. * **Maintain state**: configuration, caches, and working directories survive restarts. For structured key-value memory rather than files, see [memory stores](/docs/deep-dives/concepts/stores/memory-stores/). ## [Scopes: org vs. private](#scopes-org-vs-private) File stores come in two scopes: * **Org file stores** are shared across everyone in the organization. They’re the default for collaborative work. Any agent running under the org can read and write the same files. The org’s default store is created automatically. * **Private file stores** belong to a specific user or pod. They’re useful for personal scratch space, sensitive data that shouldn’t be shared, or isolated experiments that shouldn’t pollute the org’s shared filesystem. The scope determines visibility, not capability. Both scopes offer the same read/write semantics inside the sandbox. The difference is who can see and mount the store. ## [Managing files outside the sandbox](#managing-files-outside-the-sandbox) Beyond what agents do inside the sandbox, you can manage a store directly: * **Upload**: push a file from your local machine into the store. * **Remove**: delete a specific file. * **Purge**: clear the entire store at once. This is for seeding a store with initial data, cleaning up after a project, or removing files an agent shouldn’t be able to delete itself. ## [Creating and listing file stores](#creating-and-listing-file-stores) You can manage file stores from the CLI: ```bash ren file-stores create --name "project-data" ren file-stores list ``` The CLI is the quickest way to create stores beyond the default and see which ones exist. ## [File stores and memory stores](#file-stores-and-memory-stores) File stores and [memory stores](/docs/deep-dives/concepts/stores/memory-stores/) solve different problems and complement each other: * **File stores** hold arbitrary files such as documents, images, datasets, configs. They’re a filesystem: hierarchical, unstructured, and best for artifacts an agent produces or consumes. * **Memory stores** hold structured key-value data such as facts, preferences, session summaries. They’re a database: queryable, typed, and best for information an agent needs to recall. Most projects benefit from both. An agent might store its working files in a file store while keeping a running summary of what it’s learned in a memory store. # Memory stores > How agents remember information across sessions. A **memory store** gives an agent durable recall across sessions: preferences, decisions, conventions, accumulated knowledge. Without it, every session starts from a blank slate. You *could* use [file stores](/docs/deep-dives/concepts/stores/file-stores/) for this, but memory stores are built for retrieval: they support semantic search and selective loading into context, so an agent can recall what’s relevant without dragging everything into the prompt. ## [Memory scopes](#memory-scopes) Memory stores come in three scopes, each answering “who needs to remember this?”: * **Org memory** is shared across the whole organization. Company-wide knowledge: style guides, architectural decisions, team conventions. Every agent can read it. * **Pod memory** is private to one person’s workspace. Personal preferences, task history, notes only your agents see. * **Project memory** is scoped to a [project](/docs/deep-dives/concepts/compute/projects/). Domain-specific context: what a codebase looks like, what conventions a repo follows. Visible to every agent in that project. New organizations and users get a default memory store automatically, so agents have somewhere to write from the first session. ## [How agents use it](#how-agents-use-it) When a session starts, Ren resolves the relevant memory stores (the org default, your personal default, and any attached to the project) and makes them available in the sandbox. Small stores can be loaded directly into the agent’s context; larger ones are queried on demand, keeping the context window lean while still giving full access. A memory store can be shared across projects, and a project can mount several. So an org-wide store might be attached everywhere, while each project also keeps its own domain-specific store. ## [Memory stores vs. file stores vs. vault](#memory-stores-vs-file-stores-vs-vault) * **[File stores](/docs/deep-dives/concepts/stores/file-stores/)** are a shared drive for artifacts: code, documents, datasets. * **Memory stores** are an agent’s long-term memory: retrieval-optimized recall. * **[Vault](/docs/deep-dives/concepts/stores/vault/)** is a safe for secrets: API keys, tokens, credentials. Put an API key in the vault, a codebase in a file store, and the things an agent needs to *remember* in a memory store. ## [CLI commands](#cli-commands) ```bash ren memory-stores create --name "Team Conventions" # create a store ren memory-stores list # list stores in your org ren projects memory-stores add \ --memory-store-id # attach to a project ``` # Vault > Where Ren stores secrets and credentials. A **vault** is Ren’s encrypted credential store. API keys, OAuth tokens, environment variables, and service passwords live here so [agents](/docs/deep-dives/concepts/agents/agents/) and [MCPs](/docs/deep-dives/concepts/agents/mcps/) can authenticate against external services at runtime, without secrets ever appearing in a prompt, an agent definition, or session history. The key idea: an MCP or skill **declares** a credential slot (“I need a bearer token called `api-key`”); the vault **holds** the actual value. At runtime Ren fills the slot from the vault. The same MCP can use different credentials in different projects just by attaching different vaults. ## [Credential types](#credential-types) A vault holds up to 20 credentials, each typed so Ren knows how to inject it: | Type | When to use | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | **Bearer** | A static API token sent in the `Authorization: Bearer` header. The most common type. | | **OAuth** | Delegated auth flows (e.g. GitHub, Google Workspace). Ren stores the access token and refreshes it automatically when a refresh token is available. | | **Env** | A raw environment variable, for config values or keys that don’t fit the bearer pattern. | | **Basic** | HTTP Basic auth (username + password), for services that still require it. | ## [Encryption and archival](#encryption-and-archival) Each vault is encrypted with its own key, so compromising one vault doesn’t expose another. Ren handles encryption and decryption for you. Archiving a credential is permanent: the slot remains (so references don’t break) but the secret value is gone and must be re-created if you need it again. ## [Attaching vaults](#attaching-vaults) Vaults attach to [pods](/docs/deep-dives/concepts/compute/pods/) and [projects](/docs/deep-dives/concepts/compute/projects/) with a **priority**. When the same credential exists in more than one vault, the higher-priority vault wins. This lets you layer secrets: an org vault provides defaults, and a team vault overrides just the keys that differ. Every pod gets a **default vault** at creation, so agents always have somewhere to store and retrieve secrets. ## [How requirements are checked](#how-requirements-are-checked) When a session starts, Ren walks the project’s agents (and the skills and MCPs each one uses) and collects every credential they declare. For each one it checks whether a matching value exists in an attached vault. Anything missing is flagged before the agent runs, so you can see which agents would break and supply the secret up front. ## [OAuth](#oauth) For services that need user-delegated access (GitHub, Google Workspace), Ren runs the full OAuth flow and stores the resulting token in the vault. If the access token expires and a refresh token exists, Ren refreshes it automatically. You only re-authorize if the refresh token is revoked. ## [Using vaults from the CLI](#using-vaults-from-the-cli) ```bash ren vaults list # view vaults in your workspace ren vaults create --name "X" # create a vault ``` ## [Where to go next](#where-to-go-next) * [MCPs](/docs/deep-dives/concepts/agents/mcps/): how MCPs declare credential slots agents fill from a vault. * [Pods](/docs/deep-dives/concepts/compute/pods/): what vaults attach to, and how priority works. * [Memory stores](/docs/deep-dives/concepts/stores/memory-stores/): persistent state that isn’t secret. # Gangprompting > Coordinating multiple agents that work together on a shared goal. Coming soon A deep dive on coordinating multiple agents toward a shared goal is still being written. Watch the changelog for updates. # How Ren works > The architecture behind Ren: pods, sandboxes, and managed compute. Ren runs AI agents that do real work (writing code, calling APIs, managing data) inside isolated, managed compute. This page shows how the core pieces fit together and what happens when you run a session. ## [The stack](#the-stack) Ren is built from five primitives, layered from infrastructure up to the conversation: ```plaintext ┌─────────────────────────────────────────────┐ │ Session │ A conversation between humans and agents ├─────────────────────────────────────────────┤ │ Project │ What runs: agents, stores, permissions ├─────────────────────────────────────────────┤ │ Agent │ A versioned template: prompt, model, skills, MCPs ├─────────────────────────────────────────────┤ │ Pod │ A compute environment: server + sandbox ├─────────────────────────────────────────────┤ │ Sandbox │ Isolated code execution └─────────────────────────────────────────────┘ ``` * A [pod](/docs/deep-dives/concepts/compute/pods/) is the compute environment: a persistent server paired with an isolated sandbox where code runs. Every user gets a private pod; every organization gets a shared `general` pod. * A [project](/docs/deep-dives/concepts/compute/projects/) runs on a pod and binds what an agent can use: a primary agent and optional sub-agents, [file stores](/docs/deep-dives/concepts/stores/file-stores/), [memory stores](/docs/deep-dives/concepts/stores/memory-stores/), permissions, and an optional git repo. * An [agent](/docs/deep-dives/concepts/agents/agents/) is a versioned template: a system prompt, a model, [skills](/docs/deep-dives/concepts/agents/skills/), [MCPs](/docs/deep-dives/concepts/agents/mcps/), and a permissions policy. New sessions use the latest version; running sessions keep the version they started on. ## [Pods isolate compute and access](#pods-isolate-compute-and-access) A pod is the ownership and isolation boundary. Each member is an **owner** (can change the pod) or a **member** (can use it). One pod’s sandbox cannot see another pod’s files or processes, so a shared org pod serves a whole team without leaking state between workloads. [Vaults](/docs/deep-dives/concepts/stores/vault/) attach to pods, so credentials are scoped by pod membership. ## [Sessions stay in sync](#sessions-stay-in-sync) A [session](/docs/deep-dives/concepts/agents/sessions/) is a conversation scoped to a project on a pod. It moves through four states: `idle` (waiting for input), `busy` (the agent is working), `waiting` (the agent needs your approval or input), and `error`. When you change something on a pod (update an agent, attach a vault, add a file store), the sandbox picks up the new configuration within seconds. Changes never interrupt a turn mid-execution: a running turn finishes on the old configuration, and the next turn uses the new one. ## [Credentials resolve at runtime](#credentials-resolve-at-runtime) Agents often need credentials (API keys, OAuth tokens, database passwords) to call external services. Ren never puts secrets in prompts or configuration. Instead they live in [vaults](/docs/deep-dives/concepts/stores/vault/), encrypted at rest, and are injected into the sandbox only at execution time. When a session starts, Ren collects every credential the project’s agents, skills, and MCPs declare they need, then checks the pod’s vaults for matching values. Anything missing is flagged before the agent runs, so you find out up front instead of mid-conversation. ## [A session, end to end](#a-session-end-to-end) 1. **Start.** You send a message. Ren resolves the project, its agents, and the pod. 2. **Credential check.** Ren collects required credentials and checks the vaults. Missing ones are surfaced before the agent starts. 3. **Run.** The agent’s prompt, model, skills, and MCPs load. The model reasons, calls tools, and produces output. Credentials are available in the sandbox but never appear in the conversation. 4. **States.** The session moves through `idle` → `busy` → `waiting` → `idle` as the agent works and pauses for input. 5. **Finish.** When the task is done, the session returns to `idle`, ready for the next message. On failure it enters `error`, and you can retry or inspect the logs. # Developers > Look up exact facts: API, CLI, clients, and configuration. Reference is information-oriented and structured to match the product. Most of it is generated from the source of truth (OpenAPI spec, CLI metadata, client types) so it stays accurate. [ TypeScript SDK](/docs/developers/typescript-client/) [Methods, types, and an overview.](/docs/developers/typescript-client/) [ Ren CLI](/docs/developers/cli/) [Every `ren` command, plus config and personal access tokens.](/docs/developers/cli/) [ llms.txt](/docs/developers/llms-txt/) [Using these docs with your agent.](/docs/developers/llms-txt/) # Changelog > Notable changes to Ren. Notable, user-facing changes to Ren. Maintained manually; newest first. ## [Unreleased](#unreleased) * Documentation: new reference section covering API (Scalar), CLI, TypeScript client, and coding-agent commands, plus site-wide `llms.txt`. # Ren CLI > Install, authenticate, configure, and drive Ren from your terminal or from inside another agent. The Ren CLI (`ren`) is an agent-friendly client for the Ren API. Pair once, then drive agents, skills, MCPs, pods, and projects from your terminal, or from inside another agent’s tool call. ## [Install](#install) * npm ```bash npm install -g @renai-labs/cli ``` * npx (no install) ```bash npx @renai-labs/cli whoami ``` Once installed, `ren upgrade` pulls the latest published version (`ren upgrade --check` only reports), and `ren --version` prints the installed version. ## [Authenticate](#authenticate) 1. **Pair with your account.** For a human at a terminal, run the interactive flow: ```bash ren init ``` For agents or CI, use the non-blocking device-code flow: ```bash ren init --device-start --output json ren init --device-poll --wait 25 --output json # poll until status: signed-in ``` 2. **Confirm you’re signed in:** ```bash ren whoami ``` For non-interactive, long-lived auth (servers, CI), use a [personal access token](#personal-access-tokens-pats) via `ren pats …`. ## [Configuration](#configuration) ### [Server URLs](#server-urls) | Setting | Default | Environment variable | | --------------- | ------------------------- | -------------------- | | API server | `https://api.renai.build` | `REN_SERVER_URL` | | App (dashboard) | `https://renai.build/app` | `REN_APP_URL` | Both values have trailing slashes stripped at runtime. Override them when pointing at a self-hosted or staging instance. ### [Config directory](#config-directory) The CLI stores credentials and device-flow state under a config directory: | Path | Purpose | | --------------------------- | -------------------------------------------- | | `~/.config/ren/auth.json` | Profiles, active profile name, bearer tokens | | `~/.config/ren/device.json` | Pending device-code flow state (ephemeral) | If `XDG_CONFIG_HOME` is set, the directory becomes `$XDG_CONFIG_HOME/ren/` instead of `~/.config/ren/`. `auth.json` is written with mode `0600` (owner read/write only). The directory is `0700`. ## [Profiles](#profiles) A **profile** is a named set of credentials stored in `auth.json`. The default profile is called `default`. | Selector | Priority | Example | | ----------------------------- | ------------ | -------------------------------- | | `--profile ` flag | 1 (highest) | `ren whoami --profile work` | | `REN_PROFILE` env | 2 | `REN_PROFILE=work ren whoami` | | Active profile in `auth.json` | 3 (fallback) | Set via `ren auth switch ` | When `--profile` or `REN_PROFILE` names a profile that does not exist in `auth.json`, the CLI exits with an error. ```bash ren auth list # show all profiles and which is active ren auth switch # set a different profile as active ren auth logout # remove the active profile (or --profile ) ren auth status # alias: ren whoami ``` ## [Authentication methods](#authentication-methods) ### [Device-code flow (interactive)](#device-code-flow-interactive) Used by `ren init` for human operators at a terminal. The CLI requests a device code from the server, opens the browser to the verification URL, and polls until the user approves. The resulting bearer token is stored in `auth.json` under the resolved profile name. | Flag | Description | | ------------------ | ----------------------------------------------------------------- | | `--profile ` | Store under a named profile (default: `default` or `REN_PROFILE`) | | `--no-browser` | Print the verification URL instead of opening the browser | ### [Device-code flow (agent / CI)](#device-code-flow-agent--ci) Two-step, non-blocking variant for automation: ```bash # Step 1: start the flow, capture the verification URL ren init --device-start --output json # Step 2: poll until the user approves (or timeout) ren init --device-poll --wait 25 --output json ``` `--device-start` writes a `device.json` and exits immediately with a `verificationUrl` and `userCode`. `--device-poll` reads that file and polls the server. `--wait ` controls how long to keep polling (default `0` = single check). On success, the profile is finalized and `device.json` is removed. ### [Personal access tokens (PATs)](#personal-access-tokens-pats) PATs (format `ren_pat_*`) are long-lived bearer tokens for non-interactive use: servers, CI, scripts, the [TypeScript SDK](/docs/developers/typescript-client/). They are **not** used to log the CLI in; the CLI authenticates via `ren init`. PATs are sent as `Authorization: Bearer ren_pat_…` headers, and the API resolves them first. | Subcommand | Description | | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | `ren pats create --name --scopes … [--expires-at ]` | Create a PAT. `--scopes` is repeatable. The plaintext token is shown once. | | `ren pats list` | List active (non-revoked) PATs for the current profile. | | `ren pats revoke ` | Revoke a PAT by its ID. Revocation is immediate and permanent. | Create a PAT scoped to what you need, then use it with the [TypeScript SDK](/docs/developers/typescript-client/) or any HTTP client: ```bash ren pats create --name "ci-deploy" --scopes sessions:write --scopes projects:read ``` ## [Auth resolution priority](#auth-resolution-priority) When the CLI or API receives a request, credentials are resolved in this order: | Priority | Source | Token type | Mechanism | | -------- | ----------------------------- | --------------- | ------------------------------ | | 1 | `--profile ` flag | Bearer (stored) | Named profile from `auth.json` | | 2 | `REN_PROFILE` env | Bearer (stored) | Named profile from `auth.json` | | 3 | Active profile in `auth.json` | Bearer (stored) | Fallback | On the API side, the resolver checks the `Authorization` header for a PAT first, then the bearer token from `ren init`. The first match wins. If no credential is found, the CLI exits with: `not authenticated — run 'ren init' to pair this CLI`. ## [Scopes](#scopes) Scopes define what a token or actor can access. They are attached to PATs at creation and to sessions/PATs via org role. They use the pattern `:`: | Resource | Read scope | Write scope | | ----------------- | -------------------- | --------------------- | | Agents | `agents:read` | `agents:write` | | Skills | `skills:read` | `skills:write` | | MCPs | `mcps:read` | `mcps:write` | | Pods | `pods:read` | `pods:write` | | Sandboxes (owner) | `sandboxes:read` | `sandboxes:write` | | Projects | `projects:read` | `projects:write` | | Triggers | `triggers:read` | `triggers:write` | | Sessions | `sessions:read` | `sessions:write` | | Vaults | `vaults:read` | `vaults:write` | | Environments | `environments:read` | `environments:write` | | Memory stores | `memory-stores:read` | `memory-stores:write` | | File stores | `file-stores:read` | `file-stores:write` | | Replays | `replays:read` | `replays:write` | | Blueprints | `blueprints:read` | `blueprints:write` | | Publishers | `publishers:read` | `publishers:write` | | PATs | `pats:read` | `pats:write` | | Billing | `billing:read` | `billing:write` | | Admin | `admin` | None | When creating a PAT or assigning roles, you can reference groups that expand to multiple scopes: | Group | Expands to | | ---------- | --------------------------------------------- | | `all` | Every scope, including `admin` | | `member` | All scopes except `admin` and `billing:write` | | `readonly` | All `:read` scopes | Org roles map to scope groups: `owner` and `admin` → `all`, `member` → `member`. A PAT’s scopes cannot exceed the creator’s scopes. If you request scopes you don’t hold, creation fails and the denied scopes are listed. For a conceptual explanation of scopes and visibility, see [Scopes](/docs/deep-dives/concepts/sharing/scopes/) and [Permissions](/docs/deep-dives/concepts/sharing/permissions/). ## [Global flags](#global-flags) These flags are available on every `ren` command: | Flag / Env var | Type | Description | | ----------------------- | ------ | ----------------------------------------------------------------- | | `--output json\|pretty` | string | Output format. Defaults to `pretty` in a TTY, `json` otherwise. | | `--profile ` | string | Use a named profile. Overrides `REN_PROFILE`. | | `--help` | flag | Print command help and exit. | | `REN_SERVER_URL` | string | Override the API server URL (default: `https://api.renai.build`). | | `REN_APP_URL` | string | Override the dashboard URL (default: `https://renai.build/app`). | | `REN_PROFILE` | string | Select a profile by name. Lower priority than `--profile`. | ## [Common commands](#common-commands) A few representative commands to get started. Run `ren --help` for the full flag listing on any command. ```bash # Discover agents, skills, and MCPs across your account, org, and the registry ren agents search --query "support triage" --sources user org registry ren skills search --query "pdf" --sources user org registry # Create an agent and ship a version ren agents create --name "Release Notes" --icon "🤖" ren agents versions create --prompt "You are a release-notes writer." --model # List the available model ids ren models list # Pods & projects ren pods list ren projects create --pod-id --name "Onboarding" # Schedule the project's primary agent on a cron ren triggers create \ --project-id \ --project-agent-id \ --input-message "Summarize this week's activity" \ --schedule "0 9 * * MON" ``` Tip The CLI covers the full API surface: pods, projects, agents, skills, MCPs, triggers, replays, vaults, file/memory stores, and models. Use `ren --help` to browse the command tree, and `--output json` whenever you parse the result. ## [Issues](#issues) Bug reports and feature requests: [github.com/renai-labs/cli/issues](https://github.com/renai-labs/cli/issues). # llms.txt > Use the Ren docs as context for your AI agent. These docs are published in an LLM-friendly format so you can feed them to an agent as context. Two site-wide files are generated on every build: | File | Contents | | ---------------------------------- | ------------------------------------------------------------ | | [`/llms.txt`](/llms.txt) | An index of every page with titles, descriptions, and links. | | [`/llms-full.txt`](/llms-full.txt) | The entire documentation as a single Markdown document. | ## [Use it with your agent](#use-it-with-your-agent) Point your agent at the URL, or paste the contents in directly: ```text https://renai.build/llms-full.txt ``` For a single page, append `.md` to any docs URL (or use the “Copy as Markdown” affordance on the page) to get just that page’s Markdown. Tip `/llms.txt` is best when you want the agent to navigate and fetch only the pages it needs; `/llms-full.txt` is best when you want the whole thing in context at once. # TypeScript SDK > Install, authenticate, and call the Ren API from TypeScript with @renai-labs/sdk. `@renai-labs/sdk` is the official TypeScript client for the Ren API. It’s fully typed, generated from the same OpenAPI spec that powers the [API reference](/docs/developers/api/). ## [Install](#install) ```bash npm install @renai-labs/sdk ``` ## [Quick start](#quick-start) 1. **Create a client** with a base URL and an auth strategy: ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) ``` 2. **Call a resource.** Methods are grouped by resource and return `{ data, error, request, response }`: ```ts const { data: skills } = await client.skill.list() ``` Calls are grouped by resource: `client.agent`, `client.skill`, `client.mcp`, `client.pod`, `client.project`, `client.session`, `client.trigger`, `client.vault`, `client.credential`, `client.fileStore`, `client.memoryStore`, `client.environment`, `client.replay`, `client.blueprint`, `client.registry`, `client.pat`. Each exposes the operations available on that resource. ## [Authentication](#authentication) Authenticate with a [personal access token](/docs/developers/cli/) via the `pat` strategy, for server-side, CLI, and CI usage: ```ts import { createRenClient, pat } from "@renai-labs/sdk" createRenClient({ baseUrl, auth: pat(process.env.REN_PAT_TOKEN!) }) ``` ## [Errors](#errors) Non-2xx responses don’t throw by default. Check `error`, or opt into throwing: ```ts const { data, error } = await client.skill.get({ path: { id } }) if (error) { // error is typed to the operation's error schema } const { data } = await client.skill.get({ path: { id }, throwOnError: true }) ``` ## [Configuration](#configuration) `createRenClient` accepts any `@hey-api/client-fetch` `Config` option: `baseUrl`, `headers`, `fetch`, `credentials`, interceptors, etc. ```ts createRenClient({ baseUrl: "https://api.renai.build", auth: pat(token), headers: { "X-Request-Id": crypto.randomUUID() }, fetch: customFetch, }) ``` ## [Types only](#types-only) For apps that only need the shapes (form validators, type exports), import from the `/types` subpath to avoid pulling in the client runtime: ```ts import type { Skill, SkillCreateData } from "@renai-labs/sdk/types" ``` Note Every method and type mirrors the [API reference](/docs/developers/api/). When the API adds an endpoint, a new SDK release exposes it on the matching resource. # Guides > Goal-oriented recipes you can follow from any client. Goal-oriented recipes. Most guides lead with the UI, then show the same task from the CLI, API, and TypeScript clients. [ Build and run](/docs/guides/build-and-run/run-an-agent/) [Run agents, create skills, connect MCPs, add memory.](/docs/guides/build-and-run/run-an-agent/) [ Automate](/docs/guides/automate/schedule-cron-trigger/) [Schedule tasks and trigger sessions from your code.](/docs/guides/automate/schedule-cron-trigger/) [ Integrate](/docs/guides/integrate/slack/) [Slack, Google, Telegram, GitHub, Linear, and the browser.](/docs/guides/integrate/slack/) [ Share](/docs/guides/share/publish-to-registry/) [Publish to the registry and ship blueprints.](/docs/guides/share/publish-to-registry/) [ Admin](/docs/guides/administer/invite-teammates/) [Invite teammates, set preferences, manage permissions.](/docs/guides/administer/invite-teammates/) # Invite teammates > Add people to your Ren organization by email. Invite teammates to your organization so they can access projects, run agents, and collaborate on sessions. Before you start \- A Ren account with admin or owner role in your organization ## [Send an invitation](#send-an-invitation) ## In the UI 1. Open **Settings → Members** in the Ren dashboard. 2. Click **Invite member**. 3. Enter the email address and choose a role (owner, admin, or member). 4. Click **Send invite**. The invitee receives an email with a link to join. ## [Manage pending invitations](#manage-pending-invitations) In **Settings → Members**, pending invitations appear at the bottom of the member list. You can revoke an invitation before it’s accepted by clicking **Revoke**. Invitations expire after a set period. If an invitee’s link has expired, send a new invitation. # Manage permissions > Control what agents can do with capability-based permissions. Permissions control what an agent is allowed to do inside its sandbox: read files, run bash commands, make web requests, and more. You set permissions at the project level and can override them per agent version. Before you start * A Ren account with write access to the project or agent - [The CLI installed](/docs/developers/cli/) (for CLI steps) ## [How permissions work](#how-permissions-work) A permission config is either a single action (`"allow"`, `"deny"`, `"ask"`) or an object with granular keys. Agent-level permissions override project-level permissions. An explicit `deny` always wins over `allow`. The available permission keys are: | Key | Controls | | -------------------- | -------------------------------------------- | | `read` | Read files in the sandbox | | `edit` | Write or modify files | | `glob` | Search files by pattern | | `grep` | Search file contents | | `list` | List directory contents | | `bash` | Run shell commands | | `task` | Create and manage sub-tasks | | `external_directory` | Access directories outside the project | | `todowrite` | Write to the todo list | | `question` | Ask clarifying questions | | `webfetch` | Fetch external URLs | | `websearch` | Search the web | | `codesearch` | Search code with semantic search | | `lsp` | Use language server features | | `doom_loop` | Allow the agent to loop without intervention | | `skill` | Load and execute skills | See [Permissions](/docs/deep-dives/concepts/sharing/permissions/) for the full concept. ## [In the UI](#in-the-ui) ## In the UI 1. Open a project and go to **Settings → Permissions**. 2. Set the default policy for each capability: **Allow**, **Deny**, or **Ask**. 3. To override for a specific agent, open the agent’s version settings and adjust the permissions there. 4. Click **Save**. ## [Programmatically](#programmatically) CLI API TypeScript Select client CLI (cli) **Set project-level permissions** ```bash ren projects update prj_def456 \ --permission '{"read": "allow", "edit": "allow", "bash": "ask"}' ``` **Set agent-version-level permissions** ```bash ren agents versions create agt_abc123 \ --permission '{"bash": "deny", "webfetch": "deny"}' ``` **Set project-level permissions** ```bash curl -X PATCH "https://api.renai.build/api/projects/prj_def456" \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "permission": { "read": "allow", "edit": "allow", "bash": "ask" } }' ``` **Set agent-version-level permissions** ```bash curl -X POST "https://api.renai.build/api/agents/agt_abc123/versions" \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "permission": { "bash": "deny", "webfetch": "deny" } }' ``` ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) // Set project-level permissions await client.project.update({ path: { id: "prj_def456" }, body: { permission: { read: "allow", edit: "allow", bash: "ask" } }, }) // Override on a new agent version await client.agent.version.create({ path: { id: "agt_abc123" }, body: { version: "minor", permission: { bash: "deny", webfetch: "deny" } }, }) ``` ```plaintext ``` # Organization settings > Configure organization-wide preferences like name, logo, and timezone. Set your organization’s display name, logo, default timezone, and other preferences that apply across all projects and members. Before you start \- A Ren account with admin or owner role in your organization ## [Configure preferences](#configure-preferences) ## In the UI 1. Open **Settings → Organization** in the Ren dashboard. 2. Update the fields you want to change: * **Name**: the display name shown across the dashboard. * **Logo**: an image URL for your organization’s avatar. * **Timezone**: the default timezone for [cron triggers](/docs/guides/automate/schedule-cron-trigger/) and timestamps. Individual triggers can override this. 3. Click **Save**. The timezone you set here becomes the default for new cron triggers. Existing triggers keep their own timezone setting. # Schedule tasks > Run an agent on a time-based schedule using a cron trigger. Schedule an agent to fire automatically on a cron expression: every Monday at 09:00, every hour, or any standard 5-field schedule. Before you start * A Ren account with a [project](/docs/deep-dives/concepts/compute/projects/) that has at least one agent attached - [The CLI installed](/docs/developers/cli/), or a personal access token for the API and TypeScript calls ## [In the UI](#in-the-ui) ## In the UI 1. Open **Triggers** under your project in the sidebar. 2. Click **New trigger** and choose **Cron**. 3. Pick the agent to run, type the prompt it should receive each fire, and set the schedule (5-field cron). 4. Optionally set a timezone (defaults to UTC). 5. Click **Create**. The trigger is enabled immediately. ## [Programmatically](#programmatically) CLI API TypeScript Select client CLI (cli) **Create a cron trigger** ```bash ren triggers create \ --project-id prj_abc123 \ --project-agent-id pagt_abc123 \ --input-message "Summarize this week's activity" \ --schedule "0 9 * * MON" \ --timezone "America/New_York" ``` **List triggers in a project** ```bash ren triggers list --project-id prj_abc123 ``` **Update a trigger** (change schedule, prompt, or toggle enabled) ```bash ren triggers update trg_abc123 \ --project-id prj_abc123 \ --schedule "0 */2 * * *" \ --is-enabled false ``` **Archive a trigger** (stops the schedule permanently) ```bash ren triggers archive trg_abc123 --project-id prj_abc123 ``` **Create a cron trigger** ```bash curl -X POST https://api.renai.build/api/triggers \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "projectId": "prj_abc123", "projectAgentId": "pagt_abc123", "inputMessage": "Summarize this week'\''s activity", "schedule": "0 9 * * MON", "timezone": "America/New_York" }' ``` **List triggers** ```bash curl "https://api.renai.build/api/triggers?projectId=prj_abc123" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` **Update a trigger** ```bash curl -X PATCH "https://api.renai.build/api/triggers/trg_abc123" \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "projectId": "prj_abc123", "schedule": "0 */2 * * *", "isEnabled": false }' ``` **Archive a trigger** ```bash curl -X POST "https://api.renai.build/api/triggers/trg_abc123/archive" \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "projectId": "prj_abc123" }' ``` ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) // Create a cron trigger const { data: trigger, error } = await client.trigger.create({ body: { projectId: "prj_abc123", projectAgentId: "pagt_abc123", inputMessage: "Summarize this week's activity", schedule: "0 9 \* \* MON", timezone: "America/New_York", }, }) if (error) throw error console.log(trigger.id) // "trg_abc123" // List triggers await client.trigger.list({ query: { projectId: "prj_abc123" } }) // Update a trigger await client.trigger.update({ path: { triggerId: trigger.id }, body: { projectId: "prj*abc123", schedule: "0 */2 \_ \* \*", isEnabled: false }, }) // Archive a trigger await client.trigger.archive({ path: { triggerId: trigger.id }, body: { projectId: "prj_abc123" }, }) ``` The schedule uses standard 5-field cron syntax: `minute hour day-of-month month day-of-week`. Archiving a trigger stops it permanently. ```plaintext ``` # Trigger from a webhook > Start a session in response to an external webhook. Coming soon Webhook triggers are not yet available. To run agents on a schedule today, use [cron triggers](/docs/guides/automate/schedule-cron-trigger/). Webhook triggers will let external services (GitHub, Stripe, any HTTP source) fire a Ren session on demand. Watch the changelog for updates. # Trigger from your code > Start a new session programmatically from the CLI, API, or TypeScript. Start a new agent [session](/docs/deep-dives/concepts/agents/sessions/) from your own code. No browser needed. Use this to open sessions from CI, webhooks, or scripts, then drive them over the connection URL. Before you start * A Ren account with a [project](/docs/deep-dives/concepts/compute/projects/) and at least one [agent](/docs/deep-dives/concepts/agents/agents/) - [The CLI installed](/docs/developers/cli/), or a personal access token for the API and TypeScript calls ## [In the UI](#in-the-ui) ## In the UI 1. Open **Sessions** in the sidebar and click **New session**. 2. Choose a project and agent, then type your prompt. 3. Click **Run**. The session starts immediately. ## [Programmatically](#programmatically) Creating a session opens the agent’s sandbox and returns the session object. You then drive the session over its connection URL, or read its messages back. To start a session that runs a prompt on its own with no connection, schedule a [cron trigger](/docs/guides/automate/schedule-cron-trigger/). The trigger’s `inputMessage` is the prompt the agent receives on each fire. CLI API TypeScript Select client CLI (cli) **Create a session** ```bash ren sessions create \ --pod-id pod_abc123 \ --project-id prj_def456 \ --title "Weekly report" ``` **List sessions** ```bash ren sessions list --project-id prj_def456 ``` **Get a session’s connection URL** (for driving the session or opening it in a coding agent) ```bash ren sessions url ses_abc123 ``` **Create a session** ```bash curl -X POST https://api.renai.build/api/sessions \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "podId": "pod_abc123", "projectId": "prj_def456", "title": "Weekly report" }' ``` **List sessions** ```bash curl "https://api.renai.build/api/sessions?projectId=prj_def456" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` **Get a session’s connection URL** ```bash curl "https://api.renai.build/api/sessions/ses_abc123/url" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) // Create a session const { data: session, error } = await client.session.create({ body: { podId: "pod_abc123", projectId: "prj_def456", title: "Weekly report", }, }) if (error) throw error console.log(session.id, session.status) // "ses_abc123" "idle" // Get its connection URL to drive the session const { data: url } = await client.session.url({ path: { id: session.id } }) console.log(url.authedUrl) // "https://…" ``` ```plaintext ``` # Configure missing credentials > Resolve missing credential prompts in a chat so your agent can finish its task. When an agent needs a credential it doesn’t have, the chat surfaces a prompt so you can supply the missing API key or token inline, without leaving the session. Coming soon The full walkthrough for resolving missing credentials in a session is still being written. Watch the changelog for updates. # Create a custom MCP > Attach an external MCP server to an agent so it can call external tools. Connect an [MCP](/docs/deep-dives/concepts/agents/mcps/) (Model Context Protocol) server to an agent so the agent can call external tools at runtime. MCP servers extend what an agent can do: from searching the web to querying databases to managing infrastructure. Before you start * A Ren account and organization - [The CLI installed](/docs/developers/cli/) and paired, or a personal access token for API calls - An [agent](/docs/deep-dives/concepts/agents/agents/) version to attach the MCP to ## [Remote vs. local](#remote-vs-local) MCP servers come in two types: * **Remote**: the server is hosted at a URL. Ren proxies requests to it. Requires `mcpServerUrl`. * **Local**: the server runs as a process on the agent’s sandbox. Requires `command` (and optional `args`). The sandbox starts the process and communicates over the chosen transport. Transport options: `streamable-http` (default for remote), `sse` (server-sent events, for legacy remote servers), `stdio` (default for local). ## [Authentication](#authentication) MCP servers declare their auth requirement when you create them. Ren resolves credentials from the agent’s vault at runtime. They are never stored inline on the MCP object. | Auth type | When to use | What Ren does | | --------- | ---------------------------------------------------- | ---------------------------------------------------------------------------- | | `none` | Public or no-auth servers (default) | No credential lookup | | `api_key` | Servers that expect an API key header or query param | Reads the named credential from the vault and injects it | | `bearer` | Servers that expect a `Bearer` token | Reads the named credential and sends it as a Bearer header | | `oauth` | Servers that require OAuth 2.0 | Starts an OAuth flow, stores the token in the vault, refreshes automatically | For `api_key` and `bearer`, declare `requiredCredentials` on the MCP so Ren knows which vault entries to resolve. See [Store and share files](/docs/guides/build-and-run/store-and-share-files/) for vault setup. ## [In the UI](#in-the-ui) ## In the UI 1. Open **MCPs** in the sidebar and click **New MCP**. 2. Choose **Remote** (enter the server URL) or **Local** (enter the command and args), then pick the auth type. 3. Open the agent you want to extend, select a version, and add the MCP under **MCPs**. 4. Save. The next session on that agent version can call the MCP’s tools. ## [Create and attach programmatically](#create-and-attach-programmatically) CLI API Select client CLI (cli) 1. Create a remote MCP server: ```bash ren mcps create \ --name "web-search" \ --mcp-server-url "https://search.example.com/mcp" \ --auth none ``` Or create a local MCP server: ```bash ren mcps create \ --name "local-tools" \ --type local \ --command "npx" \ --args '["-y","@example/mcp-server"]' \ --transport stdio ``` The response includes the MCP `id` (e.g. `mcp_abc123`). 2. Attach the MCP to an agent version: ```bash ren agents versions mcps add agt_abc123 1.2.0 \ --mcp-id mcp_abc123 ``` For servers requiring an API key, declare the credential and store it in a vault: ```bash ren mcps create \ --name "paid-api" \ --mcp-server-url "https://api.example.com/mcp" \ --auth api_key \ --required-credentials '[{"name":"EXAMPLE_API_KEY","description":"API key for Example"}]' ``` Then store the key in a vault and attach the vault to the agent’s pod. 1. Create a remote MCP server with `POST /api/mcps`: ```bash curl -X POST https://api.renai.build/api/mcps \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "web-search", "mcpServerUrl": "https://search.example.com/mcp", "type": "remote", "transport": "streamable-http", "auth": "none" }' ``` Or create a local MCP server: ```bash curl -X POST https://api.renai.build/api/mcps \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "local-tools", "type": "local", "command": "npx", "args": ["-y", "@example/mcp-server"], "transport": "stdio" }' ``` 2. Attach the MCP to an agent version with `POST /api/agents/{id}/versions/{version}/mcps`: ```bash curl -X POST https://api.renai.build/api/agents/agt_abc123/versions/1.2.0/mcps \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"mcpId": "mcp_abc123"}' ``` For OAuth-authenticated servers, start the OAuth flow after creation: ```bash curl -X POST https://api.renai.build/api/mcps/mcp_abc123/oauth/connect \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` This returns an authorization URL. Complete the flow in a browser, then poll the session endpoint until `status` is `connected`. # Create a skill > Author a Ren skill, upload it, and attach it to an agent version. Create a [skill](/docs/deep-dives/concepts/agents/skills/), upload its archive, and attach it to an agent version so the agent can load it at runtime. A skill is a packaged capability (a `SKILL.md` with frontmatter, plus optional scripts and assets) that an agent loads on demand when a task makes it relevant. Before you start * A Ren account and organization - [The CLI installed](/docs/developers/cli/) and paired, or a personal access token for API calls - An [agent](/docs/deep-dives/concepts/agents/agents/) version to attach the skill to ## [Author the SKILL.md](#author-the-skillmd) A skill starts with a `SKILL.md` file in the root of its archive. The frontmatter defines metadata; the body is the instruction text the agent reads. ```markdown --- name: summarize-commits description: Summarize recent git commits into a changelog entry. requiredCredentials: - name: GITHUB_TOKEN description: Personal access token with repo read scope --- You are a commit summarizer. When given a repository path and a date range: 1. Run `git log --oneline --since= --until=`. 2. Group related commits. 3. Write a changelog entry in Keep a Changelog format. ``` The `name` must be hyphen-case, 1 to 64 characters. The `description` is 1 to 1024 characters. `requiredCredentials` is an optional array of `{ name, description? }`. Credential names use `UPPER_SNAKE_CASE` and are resolved from the agent’s vault at runtime, never stored inline. The first version defaults to `0.0.1` if you don’t specify one. ## [In the UI](#in-the-ui) ## In the UI 1. Open **Skills** in the sidebar and click **New skill**. 2. Enter a name, then upload your skill folder (the one containing `SKILL.md`) to create the first version. 3. Open the agent you want to give the skill to, select a version, and add the skill under **Skills**. 4. Save. The next session on that agent version loads the skill on demand. ## [Upload and attach programmatically](#upload-and-attach-programmatically) Skills are uploaded as archives (a `.tar.gz` or a set of files). After creating the skill and a version, attach it to an agent version so the agent can use it. CLI API Select client CLI (cli) 1. Create the skill: ```bash ren skills create --name "summarize-commits" ``` The response includes the skill `id` (e.g. `skl_abc123`). 2. Create a version with your archive: ```bash ren skills versions create skl_abc123 \ --version 0.0.1 \ --archive ./skill-folder/ ``` You can also point to a Git ref instead of uploading a local archive: ```bash ren skills versions create skl_abc123 \ --version 0.0.1 \ --source '{"type":"git","url":"https://github.com/example/skill.git","ref":"main"}' ``` 3. Attach the skill version to an agent version: ```bash ren agents versions skills add agt_abc123 1.2.0 \ --skill-id skl_abc123 \ --skill-version 0.0.1 ``` Use `ren skills list` to see all your skills and `ren skills versions list ` to inspect versions. 1. Create the skill with `POST /api/skills`: ```bash curl -X POST https://api.renai.build/api/skills \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -F "name=summarize-commits" \ -F "files=@./SKILL.md" ``` The response includes the skill `id`. 2. Create a version with `POST /api/skills/{id}/versions`: ```bash curl -X POST https://api.renai.build/api/skills/skl_abc123/versions \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -F "version=0.0.1" \ -F "files=@./SKILL.md" \ -F "files=@./scripts/summarize.sh" ``` 3. Attach the skill to an agent version with `POST /api/agents/{id}/versions/{version}/skills`: ```bash curl -X POST https://api.renai.build/api/agents/agt_abc123/versions/1.2.0/skills \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"skillId": "skl_abc123", "skillVersion": "0.0.1"}' ``` Skill scope determines visibility: **private** (default, only your org), **org** (all org members), or **public** (published to the registry). Publish with `ren skills publish skl_abc123` or `POST /api/skills/{id}/publish`. # Give an agent memory > Add a memory store so an agent remembers across sessions. Give an agent persistent memory by creating a memory store and attaching it to a project. Memory stores survive across sessions. The agent can write facts, preferences, and context that carry over from one run to the next. Small stores are loaded into the agent’s context at session start; larger ones are exposed as a retrieval tool the agent queries on demand. Before you start * A Ren account with at least one [project](/docs/deep-dives/concepts/compute/projects/) - [The CLI installed](/docs/developers/cli/) and paired, or a personal access token for the API and TypeScript calls ## [In the UI](#in-the-ui) ## In the UI 1. Navigate to your project’s **Settings** tab. 2. Under **Memory stores**, click **Add memory store**. 3. Choose an existing store or create a new one by entering a name. 4. The store is now attached. The next session on this project will have access to it. ## [Programmatically](#programmatically) Create a memory store, then attach it to a project. Each project can have multiple memory stores, and each store can be shared across projects. CLI API TypeScript Select client CLI (cli) 1. Create a memory store: ```bash ren memory-stores create --name "project-context" ``` The response includes the store `id` (e.g. `mst_abc123`). 2. Attach it to a project: ```bash ren projects memory-stores add prj_def456 \ --memory-store-id mst_abc123 ``` 3. Upload a file to the store (optional: the agent can also write to it at runtime): ```bash ren memory-stores files upload mst_abc123 \ --path "context.md" \ --file ./context.md ``` List stores and their files: ```bash ren memory-stores list ren memory-stores files list mst_abc123 ``` Detach a store from a project: ```bash ren projects memory-stores remove prj_def456 mst_abc123 ``` 1. Create a memory store with `POST /api/memory-stores`: ```bash curl -X POST https://api.renai.build/api/memory-stores \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "project-context"}' ``` The response includes the store `id`. 2. Attach it to a project with `POST /api/projects/{id}/memory-stores`: ```bash curl -X POST https://api.renai.build/api/projects/prj_def456/memory-stores \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"memoryStoreId": "mst_abc123"}' ``` 3. Upload a file to the store (two-step: presign, then PUT): ```bash # Start the upload curl -X POST https://api.renai.build/api/memory-stores/mst_abc123/files/uploads \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"path": "context.md", "contentType": "text/markdown"}' # PUT the file to the presigned URL returned above, then finalize: curl -X POST https://api.renai.build/api/memory-stores/mst_abc123/files/finalize \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"path": "context.md"}' ``` Create a memory store and attach it to a project: ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) const { data: store, error } = await client.memoryStore.create({ body: { name: "project-context" }, }) if (error) throw error console.log(store.id) // "mst_abc123" await client.project.memoryStore.add({ path: { id: "prj_def456" }, body: { memoryStoreId: store.id }, }) ``` Upload files to a store with the CLI (`ren memory-stores files upload`). The agent can also write to the store at runtime. Memory stores are scoped to an owner (org or user). One store per owner can be marked `isDefault`. It’s automatically attached to new projects in that scope. # Run an agent > Start an agent run from any client: create a session and send a message. Start an agent run by creating a [session](/docs/deep-dives/concepts/agents/sessions/) on a project and sending it a prompt. A session is a single conversation with an agent. It tracks messages, permissions, and state from idle through completion. This guide covers starting a run interactively. To kick off unattended runs from CI or your own scripts, see [Trigger from your code](/docs/guides/automate/trigger-session-via-api/). Before you start * A Ren account with at least one [pod](/docs/deep-dives/concepts/compute/pods/) and [project](/docs/deep-dives/concepts/compute/projects/) - An [agent](/docs/deep-dives/concepts/agents/agents/) version deployed to that project ## [In the UI](#in-the-ui) ## In the UI 1. Open the project you want to run the agent in. 2. Click **Run** (or the play icon next to the agent version). 3. Type your prompt and press Enter. The session starts in `busy` state and transitions to `idle` when the agent finishes. 4. To continue the conversation, type another message. The session stays open until you archive it. ## [Programmatically](#programmatically) Sessions are created against a pod and project. You need the pod ID and project ID. Both are visible in the UI, or list them with `ren pods list` / `ren projects list`. A session moves through these statuses: `idle` (waiting for input), `busy` (agent is working), `waiting` (agent needs a permission decision), and `error`. Claude Code Codex opencode ![](/hermes-agent.webp) Hermes CLI API TypeScript Select client Claude Code (claude-code) Use the `/ren:run` slash command inside a Claude Code session, or paste a prompt that starts with `ren:`: ```plaintext /ren:run my-agent ``` This creates a session on your default pod and project, sends the prompt, and streams the agent’s reply back into the Claude Code chat. For non-interactive runs (CI, automation), permissions are auto-allowed. See the [Give your agent access to Ren](/docs/tutorials/give-agent-access-to-ren/). Use the `$ren-onboarding` command to start a session, or invoke the Ren MCP tool directly: ```plaintext $ren-onboarding ``` For subsequent runs, the Ren MCP tool `session.create` is available. See [Give your agent access to Ren](/docs/tutorials/give-agent-access-to-ren/) for install instructions. Use the `/ren:run` slash command: ```plaintext /ren:run my-agent ``` This creates a session and sends the prompt. The agent’s response streams back into the opencode chat. Use the `/ren-onboarding` command to start a session: ```plaintext /ren-onboarding ``` After onboarding, the Ren MCP tools (`session.create`, `session.list`) are available in the Hermes chat for programmatic session management. Create a session on a pod and project: ```bash ren sessions create \ --pod-id pod_abc123 \ --project-id prj_def456 \ --title "First run" ``` List sessions to find IDs: ```bash ren sessions list --pod-id pod_abc123 ``` Get a session’s connection URL (for browser access or driving the session): ```bash ren sessions url ses_abc123 ``` Create a session with `POST /api/sessions`: ```bash curl -X POST https://api.renai.build/api/sessions \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "podId": "pod_abc123", "projectId": "prj_def456", "title": "First run" }' ``` The response includes the session `id`, `status`, and `slug`. To connect after creation, get the session’s connection URL with `GET /api/sessions/{id}/url`. Use the [TypeScript client](/docs/developers/typescript-client/) to create a session: ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) const { data: session, error } = await client.session.create({ body: { podId: "pod_abc123", projectId: "prj_def456", title: "First run", }, }) if (error) throw error console.log(session.id, session.status) // "ses_abc123" "busy" ``` To get the session’s connection URL (for connecting a WebSocket or browser): ```ts const { data: urlData } = await client.session.url({ path: { id: session.id }, }) console.log(urlData.authedUrl) // "https://…" ``` # Store and share files > Use file stores to persist and share files between agent runs. Create a file store, upload files to it, and attach it to a project so the agent can read and write persistent files across sessions. File stores materialize as real directories in the agent’s sandbox. The agent sees them as a normal filesystem path, not an API. Before you start * A Ren account with at least one [project](/docs/deep-dives/concepts/compute/projects/) - [The CLI installed](/docs/developers/cli/) and paired, or a personal access token for the API and TypeScript calls ## [In the UI](#in-the-ui) ## In the UI 1. Navigate to your project’s **Settings** tab. 2. Under **File stores**, click **Add file store**. 3. Choose an existing store or create a new one by entering a name. 4. Upload files to the store through the file browser. 5. The store is now attached. The next session on this project will see it as a directory. ## [Programmatically](#programmatically) Create a file store, upload files, and attach it to a project. Each project can have multiple file stores, and each store can be shared across projects. CLI API TypeScript Select client CLI (cli) 1. Create a file store: ```bash ren file-stores create --name "project-data" ``` The response includes the store `id` (e.g. `fst_abc123`). 2. Upload a file to the store: ```bash ren file-stores files upload fst_abc123 \ --path "data/config.json" \ --file ./config.json ``` 3. Attach the store to a project: ```bash ren projects file-stores add prj_def456 \ --file-store-id fst_abc123 ``` List stores and their files: ```bash ren file-stores list ren file-stores files list fst_abc123 ``` Remove a file from the store: ```bash ren file-stores files remove fst_abc123 --path "data/config.json" ``` Detach a store from a project: ```bash ren projects file-stores remove prj_def456 fst_abc123 ``` 1. Create a file store with `POST /api/file-stores`: ```bash curl -X POST https://api.renai.build/api/file-stores \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "project-data"}' ``` The response includes the store `id`. 2. Upload a file (two-step: presign, then PUT): ```bash # Start the upload — get a presigned URL curl -X POST https://api.renai.build/api/file-stores/fst_abc123/files/uploads \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"path": "data/config.json", "contentType": "application/json"}' # PUT the file to the presigned URL returned above, then finalize: curl -X POST https://api.renai.build/api/file-stores/fst_abc123/files/finalize \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"path": "data/config.json"}' ``` 3. Attach the store to a project with `POST /api/projects/{id}/file-stores`: ```bash curl -X POST https://api.renai.build/api/projects/prj_def456/file-stores \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"fileStoreId": "fst_abc123"}' ``` Create a file store and attach it to a project: ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) const { data: store, error } = await client.fileStore.create({ body: { name: "project-data" }, }) if (error) throw error console.log(store.id) // "fst_abc123" await client.project.fileStore.add({ path: { id: "prj_def456" }, body: { fileStoreId: store.id }, }) ``` Upload files with the CLI (`ren file-stores files upload`), or use the two-step presign-and-PUT flow shown in the API tab. File stores are scoped to an owner (org or user). One store per owner can be marked `isDefault`. It’s automatically attached to new projects in that scope. When an agent modifies files in a store, the changes persist. The next session on the same project picks up where the last one left off. # Browser > Give an agent browser access for navigating, filling forms, and extracting data from the web. Every Ren pod includes a managed Playwright browser. No setup required. Agents can navigate pages, fill forms, click buttons, extract data, and interact with web interfaces, all inside the sandbox. The browser has access to the session’s vault credentials for authenticated browsing. Before you start \- A Ren account with a [project](/docs/deep-dives/concepts/compute/projects/) and agent ## [How it works](#how-it-works) The browser is provided as a local MCP server (`browser`) that runs inside the pod. When an agent needs to browse, it calls one of the browser tools: | Tool | What it does | | ------------------------ | -------------------------------------------------- | | `browser_create_session` | Open a new browser session and get a live-view URL | | `browser_navigate` | Go to a URL | | `browser_screenshot` | Capture the current page | | `browser_click` | Click an element | | `browser_type` | Type text into an input | | `browser_scroll` | Scroll the page | | `browser_evaluate` | Run JavaScript in the page context | | `browser_close_session` | Close the session and get a replay URL | The browser is available automatically. You don’t need to add it as an MCP server or configure anything. Agents discover it at runtime. ## [Using the browser in prompts and skills](#using-the-browser-in-prompts-and-skills) Reference browser actions directly in a prompt or [skill](/docs/guides/build-and-run/create-a-skill/) instructions: ```plaintext Go to https://example.com/dashboard, log in using the credentials from the vault, and take a screenshot of the analytics page. ``` For authenticated browsing, store credentials in a [vault](/docs/deep-dives/concepts/stores/vault/) attached to the pod. The browser can access them during the session. # GitHub > Connect Ren to GitHub so agents can read and write code, open PRs, and review issues. Connect the Ren GitHub App to your organization so agents can clone repos, push commits, open pull requests, and comment on issues, all inside their sandbox. Before you start * A Ren account with admin access to your organization - A GitHub account with permission to install GitHub Apps - At least one [project](/docs/deep-dives/concepts/compute/projects/) where you want to attach a repo ## [Install the GitHub App](#install-the-github-app) ## In the UI 1. Open **Settings → Integrations → GitHub** in the Ren dashboard. 2. Click **Connect GitHub**. You’ll be redirected to GitHub to install the Ren GitHub App. 3. Choose which repositories the app can access (all or selected repos). 4. After approval, you’re returned to Ren. The installation is now linked to your organization. ## [Attach a repo to a project](#attach-a-repo-to-a-project) Once the GitHub App is installed, you can bind a repository to any project. Agents in that project will clone the repo into their sandbox and can push branches, open PRs, and more. 1. Open the project you want to configure. 2. In **Project settings → Git repo**, select the repository from the dropdown. 3. Save. The next session in this project will automatically clone the repo. ## [Connect your personal GitHub account (optional)](#connect-your-personal-github-account-optional) For operations that require a user-level OAuth token (such as commenting on behalf of a specific user), connect your personal GitHub account under **Settings → Integrations → GitHub → Connect account**. ## [Disconnect GitHub](#disconnect-github) In **Settings → Integrations → GitHub**, click **Disconnect**. This removes the GitHub App installation and revokes Ren’s access to your repositories. # Google > Connect Ren agents to Google services. Coming soon Google integration is not yet available. When released, it will let Ren agents read and act on Gmail, Calendar, and Drive from within sessions. Watch the changelog for updates. # Linear > Connect Ren to Linear. Coming soon Linear integration is not yet available. When released, it will let Ren agents read and update Linear issues, post comments, and create new issues from within sessions. Watch the changelog for updates. # Slack > Connect Ren to your Slack workspace and route channels to projects. Connect Ren to Slack so that messages in mapped channels create agent sessions, and agents can reply directly in threads. Before you start * A Ren account with admin access to your organization - A Slack workspace where you can install apps - At least one [project](/docs/deep-dives/concepts/compute/projects/) with an agent attached ## [Install the Slack app](#install-the-slack-app) ## In the UI 1. Open **Settings → Integrations → Slack** in the Ren dashboard. 2. Click **Connect Slack**. You’ll be redirected to Slack to authorize the Ren bot for your Slack workspace. 3. After approval, you’re returned to Ren. The Slack workspace is now linked to your organization. ## [Map channels to projects](#map-channels-to-projects) Each Slack channel can be mapped to one Ren project. When someone posts in a mapped channel, Ren creates a session using the project’s primary agent (or the default agent you specify). 1. In **Settings → Integrations → Slack**, click **Map channel**. 2. Select a Slack channel and a Ren project. 3. Optionally choose a **default agent** and a **fallback sender** (the Ren user whose identity the agent uses when posting). 4. Click **Save**. Messages in that channel now trigger agent sessions. To remove a mapping, click the channel’s **Unmap** button. The Slack bot remains installed. Only the routing is removed. ## [Disconnect Slack](#disconnect-slack) In **Settings → Integrations → Slack**, click **Disconnect**. This removes the Slack bot from your Slack workspace and deletes all channel mappings. # Telegram > Connect Ren agents to Telegram. Coming soon Telegram integration is not yet available. When released, it will let Ren agents send and receive Telegram messages so you can run them from a chat. Watch the changelog for updates. # Build and install a blueprint > Package a setup as a blueprint and install it elsewhere. A blueprint is a portable deployment package: a snapshot of projects, agents, skills, MCPs, and cron triggers that can be installed into any pod. Build one from your existing resources, then install it from the registry to recreate that setup in a new environment. Before you start * A Ren account with at least one project, agent, or skill you want to package - A personal access token for the API and TypeScript calls ## [How blueprints work](#how-blueprints-work) A blueprint template contains: * **Projects**: names, descriptions, permissions, and agent assignments * **Agents**: references (or forks) with their skill and MCP dependencies * **Skills**: references (or forks) with version pins * **MCPs**: references (or forks) * **Cron triggers**: schedules, prompts, and timezones (installed disabled by default) When you install, Ren resolves each resource: if you can reference the original (same org or public), it links; otherwise it forks a copy into your pod. See [Blueprints](/docs/deep-dives/concepts/sharing/blueprints/) for the full concept. ## [In the UI](#in-the-ui) ## In the UI 1. Open **Blueprints** in the sidebar and click **New blueprint**. 2. Select the projects, agents, skills, and MCPs to include. 3. Click **Create**. The blueprint is saved as a draft. 4. To share it, click **Publish to registry**. 5. To install, browse the registry, pick a blueprint, and click **Install**. ## [Programmatically](#programmatically) API TypeScript Select client API (api) **Create a blueprint** ```bash curl -X POST https://api.renai.build/api/blueprints \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Customer support", "description": "Support agent with knowledge base", "selection": { "projectIds": ["prj_def456"], "agentIds": ["agt_abc123"], "skillIds": ["skl_abc123"] } }' ``` **Publish a blueprint** ```bash curl -X POST "https://api.renai.build/api/blueprints/blt_abc123/publish" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` **Install a blueprint** into a pod. `source` is the blueprint’s id or slug: ```bash curl -X POST "https://api.renai.build/api/blueprints/install" \ -H "Authorization: Bearer $REN_PAT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "source": "blt_abc123", "podId": "pod_abc123" }' ``` ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) // Create a blueprint const { data: blueprint, error } = await client.blueprint.create({ body: { name: "Customer support", description: "Support agent with knowledge base", selection: { projectIds: ["prj_def456"], agentIds: ["agt_abc123"], skillIds: ["skl_abc123"], }, }, }) if (error) throw error console.log(blueprint.id) // "blt_abc123" // Publish it to the registry await client.blueprint.publish({ path: { id: blueprint.id } }) // Install it into a pod await client.blueprint.install({ body: { source: blueprint.id, podId: "pod_abc123" }, }) ``` ```plaintext ``` # Publish to the registry > Publish an agent, skill, or MCP to the Ren registry so others can discover and reuse it. Publishing makes a resource visible on the Ren registry. Once published, anyone in your organization (or the public, depending on scope) can discover and reference it. Publishing is one-way. You can deprecate a resource, but you cannot unpublish it. Before you start * A Ren account with a resource (agent, skill, or MCP) you want to publish - [The CLI installed](/docs/developers/cli/), or a personal access token for the API and TypeScript calls ## [How publishing works](#how-publishing-works) When you publish, Ren: 1. Creates a publisher for your organization if one doesn’t already exist. 2. Sets the resource’s `publisherId`, making it discoverable on the registry. 3. Auto-publishes any dependent resources that aren’t yet published (e.g. an agent’s skills and MCPs). Published resources move from **private** scope to **org** or **public** scope. See [Scopes](/docs/deep-dives/concepts/sharing/scopes/) for details. ## [In the UI](#in-the-ui) ## In the UI 1. Open the resource (agent, skill, or MCP) you want to publish. 2. Click **Publish to registry**. 3. Confirm. The resource is now visible on the registry. ## [Programmatically](#programmatically) CLI API TypeScript Select client CLI (cli) **Publish an agent** ```bash ren agents publish agt_abc123 ``` **Publish a skill** ```bash ren skills publish skl_abc123 ``` **Publish an MCP** ```bash ren mcps publish mcp_abc123 ``` **Publish an agent** ```bash curl -X POST "https://api.renai.build/api/agents/agt_abc123/publish" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` **Publish a skill** ```bash curl -X POST "https://api.renai.build/api/skills/skl_abc123/publish" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` **Publish an MCP** ```bash curl -X POST "https://api.renai.build/api/mcps/mcp_abc123/publish" \ -H "Authorization: Bearer $REN_PAT_TOKEN" ``` ```ts import { createRenClient, pat } from "@renai-labs/sdk" const client = createRenClient({ baseUrl: "https://api.renai.build", auth: pat(process.env.REN_PAT_TOKEN!), }) await client.agent.publish({ path: { id: "agt_abc123" } }) await client.skill.publish({ path: { id: "skl_abc123" } }) await client.mcp.publish({ path: { id: "mcp_abc123" } }) ``` Publishing is permanent. There is no unpublish. To stop showing a resource, use **Deprecate** instead, which marks it as deprecated on the registry while keeping it functional for existing references. ```plaintext ``` # Tutorials > Learn Ren by doing: guided, end-to-end lessons. Guided, end-to-end lessons. Follow them in order, then use the [guides](/docs/guides/) for specific goals. [ Quickstart](/docs/tutorials/quickstart/) [The shortest path to your first chat with a Ren agent.](/docs/tutorials/quickstart/) [ Create an agent on Slack](/docs/tutorials/new-agent-on-slack/) [Build a custom agent in the UI and chat with it from Slack.](/docs/tutorials/new-agent-on-slack/) [ Give your agent access to Ren](/docs/tutorials/give-agent-access-to-ren/) [Run Ren from your coding agent and deploy your agent stack.](/docs/tutorials/give-agent-access-to-ren/) # Give your agent access to Ren > Run Ren from your coding agent and deploy your agent stack so every client (coding agents, MCPs, and the SDK) can reach it. Ren is one backend with many ways in. In this tutorial you’ll connect Ren to the coding agent you already use (for example, Claude Code), run Ren from inside it, and deploy your agent stack so it’s reachable from every client: coding agents, MCPs, and the SDK. Before you start \- A Ren account - A supported coding agent installed locally (such as Claude Code) ## [1. Run Ren from your coding agent](#1-run-ren-from-your-coding-agent) Install the Ren plugin into your coding agent so it can pair the [Ren CLI](/docs/developers/cli/) and call Ren on your behalf. 1. Install the Ren plugin for your coding agent. 2. Pair it with your account. The plugin runs `ren init` and signs you in. 3. Confirm the connection: ```bash ren whoami ``` Your coding agent can now create sessions, run agents, and manage resources on Ren directly from your editor. ## [2. Deploy your agent stack to Ren](#2-deploy-your-agent-stack-to-ren) Define your agents, skills, and MCPs as code, then deploy them to Ren so they run on managed compute instead of your laptop. 1. From your coding agent, create an [agent](/docs/deep-dives/concepts/agents/agents/) and publish a version with its system prompt and model. 2. Attach [skills](/docs/deep-dives/concepts/agents/skills/) and [MCP servers](/docs/deep-dives/concepts/agents/mcps/) the agent needs. 3. Deploy the stack to a [project](/docs/deep-dives/concepts/compute/projects/) on your pod. Once deployed, the stack lives on Ren: versioned, observable, and shareable across your org. ## [3. Reach it from every client](#3-reach-it-from-every-client) Because the stack runs on Ren’s backend, the same agents are reachable from any entry point: | Client | How it connects | | -------------- | ------------------------------------------------------------------------ | | Coding agents | Through the Ren plugin and CLI, from inside your editor | | MCPs | The Ren MCP tools (such as `session.create`) expose your agents to tools | | TypeScript SDK | The [TypeScript SDK](/docs/developers/typescript-client/) wraps the API | | CLI / API | The [Ren CLI](/docs/developers/cli/) and REST API drive everything | ## [What you built](#what-you-built) You connected your coding agent to Ren, deployed an agent stack to managed compute, and made it reachable from every Ren client. ## [Next steps](#next-steps) * Automate runs with [Schedule tasks](/docs/guides/automate/schedule-cron-trigger/) or [Trigger from your code](/docs/guides/automate/trigger-session-via-api/). * Share what you built by [publishing to the registry](/docs/guides/share/publish-to-registry/). # Create an agent on Slack > Build a custom agent in the Ren UI, connect it to a Slack channel, and start a chat from Slack. In this tutorial you’ll build a custom agent in the Ren UI, connect it to a Slack channel, and start a conversation with it directly from Slack. Everything here happens in the UI. No CLI required. Before you start * A Ren account - A Slack workspace where you can install apps (or an admin who can approve the Ren Slack app) ## [1. Create a custom agent](#1-create-a-custom-agent) In the Ren dashboard, open **Agents** and click **New agent**. 1. Give the agent a **name** and an **icon** so it’s easy to recognize in Slack. 2. Write a **system prompt** that defines what the agent does and how it should behave. Keep it specific. 3. Pick a **model** for this version. 4. Save to publish the agent’s first version. Your agent now lives in your default project on your auto-provisioned pod. You can attach [skills](/docs/deep-dives/concepts/agents/skills/) and [MCP servers](/docs/deep-dives/concepts/agents/mcps/) later to expand what it can do. ## [2. Connect Slack](#2-connect-slack) Open **Integrations → Slack** and click **Connect**. Ren walks you through installing the Slack app and authorizing your Slack workspace. 1. Approve the Ren Slack app in your Slack workspace. 2. Choose the **channel** where the agent should be available. 3. Select the **agent** you created in step 1 as the channel’s agent. Once connected, the agent is a member of that channel and listens for messages directed at it. ## [3. Start a chat from Slack](#3-start-a-chat-from-slack) In the connected Slack channel, mention the agent or send it a direct message: ```text @your-agent Summarize the latest release notes and post the highlights here. ``` The agent runs on Ren, streams its work back into the Slack thread, and replies in the channel. Every exchange is captured as a [session](/docs/deep-dives/concepts/agents/sessions/) you can open and replay from the dashboard. ## [What you built](#what-you-built) | Piece | What it does | | ------------- | ------------------------------------------------------- | | Agent | A custom agent with your system prompt and model | | Slack channel | Where teammates talk to the agent in their own workflow | | Session | A recorded, replayable record of each conversation | ## [Next steps](#next-steps) * Give the agent more capability with a [skill](/docs/guides/build-and-run/create-a-skill/) or a [custom MCP](/docs/guides/build-and-run/create-a-custom-mcp/). * Let it run on a schedule with [Schedule tasks](/docs/guides/automate/schedule-cron-trigger/). * Connect more tools from the [Integrate](/docs/guides/integrate/slack/) guides. # Quickstart > The shortest path to your first session on Ren. Install the CLI, pair it with your account, set up a pod and project, create an agent, and send your first message. Before you start \- A Ren account - Node.js 18 or later ## [1. Install the CLI](#1-install-the-cli) ```bash npm install -g @renai-labs/cli ``` Verify the install: ```bash ren --version ``` For full install options (including Homebrew and manual binary), see [Install the CLI](/docs/developers/cli/). ## [2. Pair with your account](#2-pair-with-your-account) ```bash ren init ``` The CLI opens a browser to authenticate. Approve the pairing request, then return to your terminal. Confirm you’re paired: ```bash ren whoami ``` You should see your account details printed. ## [3. Find or create a pod](#3-find-or-create-a-pod) A [pod](/docs/deep-dives/concepts/compute/pods/) is the compute environment where your agents run. Check if you already have one: ```bash ren pods list ``` If a pod appears, note its ID and skip ahead to step 4. If the list is empty, create one: ```bash ren pods create --name "My Pod" ``` Note the `podId` from the output. You’ll need it next. ## [4. Create a project](#4-create-a-project) A [project](/docs/deep-dives/concepts/compute/projects/) groups agents and their sessions inside a pod. ```bash ren projects create --pod-id --name "Onboarding" ``` Replace `` with the ID from step 3. Note the `projectId` from the output. ## [5. Create an agent and add it to the project](#5-create-an-agent-and-add-it-to-the-project) An [agent](/docs/deep-dives/concepts/agents/agents/) is the AI worker that carries out tasks. Create the agent: ```bash ren agents create --name "My Agent" --icon "🤖" ``` Note the `agentId` from the output. List the available models and copy an id: ```bash ren models list ``` Create a version with a system prompt and one of those model ids: ```bash ren agents versions create --prompt "You are a helpful assistant." --model ``` Add the agent to your project: ```bash ren projects agents add --agent-id ``` ## [6. Start a session and open it](#6-start-a-session-and-open-it) Create a [session](/docs/deep-dives/concepts/agents/sessions/) against your pod and project: ```bash ren sessions create --pod-id --project-id --title "First chat" ``` Note the session `id` from the output, then get its connection URL: ```bash ren sessions url ``` Open that URL in your browser to chat with your agent. That’s your first session running on Ren. To drive sessions from your own code instead, see the [TypeScript SDK](/docs/developers/typescript-client/). # Why Ren? > The technical challenges of becoming an AI-native company, why Ren exists, and how it compares to the status quo. ## [The problem](#the-problem) Every company that wants to put AI agents to work hits the same wall. A coding agent in your terminal is impressive. It reads files, writes code, runs tests. But the moment you need that agent to operate as a real member of your team, a cascade of infrastructure problems appears: * **Where does it run?** An agent that modifies production code needs a real machine with real compute, not your laptop. * **How does it authenticate?** It needs API keys, cloud credentials, database access, and those secrets can’t live in a chat window. * **How does it talk to your tools?** Slack, GitHub, your CI pipeline, your browser. Each integration is bespoke glue code. * **How do you watch it?** When an agent runs for hours, you need to know what it did, why, and whether it went off the rails. * **How do you scale it?** One agent is a prototype. Ten agents coordinating across a codebase is an engineering problem. Most teams solve these problems with duct tape: a Docker container here, a `.env` file there, a cron job, a Slack webhook. It works for a demo. It falls apart in production. ## [What Ren is](#what-ren-is) Ren is a **managed agent deployment platform**. It runs coding agents (powered by [opencode](https://opencode.ai)) inside managed sandboxes and gives them everything they need to operate as reliable, observable members of your engineering organization. Instead of stitching together infrastructure yourself, Ren provides: * **Managed sandbox compute**: [Pods](/docs/deep-dives/concepts/compute/pods/) provision isolated environments with real CPUs, memory, and filesystems. Agents run on dedicated infrastructure, not on someone’s laptop. * **Multiplayer sessions**: [Sessions](/docs/deep-dives/concepts/agents/sessions/) let humans and agents collaborate in the same session at the same time. Watch an agent work, jump in to correct course, hand off again. * **Vault and credential management**: A [Vault](/docs/deep-dives/concepts/stores/vault/) stores encrypted secrets and injects them into agents at runtime. No `.env` files, no leaked keys in chat logs. * **Native integrations**: Slack, GitHub, browser automation, and more are first-class. Agents don’t need custom glue code to interact with your existing tools. * **Scheduling and webhooks**: Agents can run on cron schedules, react to webhook events, or be invoked on demand. Long-running tasks stay alive for hours or days. * **Multi-agent coordination**: [Agents](/docs/deep-dives/concepts/agents/agents/) can be composed into societies where specialist agents hand off work to each other, each with its own skills and permissions. * **Org-level skill and MCP registry**: Skills and MCP servers are shared across your organization, versioned, and scoped. No copy-pasting prompts between team members. * **Session replays**: Every agent action is recorded. Replay a session to audit decisions, debug failures, or onboard new team members. * **Model-agnostic**: Swap the underlying model without rearchitecting. Ren’s agent runtime is decoupled from any single LLM provider. ## [What Ren is not](#what-ren-is-not) Ren is opinionated about what it is not, because the boundaries matter: * **Not a chat wrapper.** Ren doesn’t put a thin UI over an API call. Agents run in full sandboxed environments with real tooling and real state. * **Not a no-code workflow builder.** There’s no visual drag-and-drop canvas. Agents are configured through code, skills, and MCPs: the same primitives your engineers already use. * **Not a single-agent chatbot.** Ren is built for multi-agent systems from the ground up. If you need one agent in one chat window, simpler tools exist. ## [How Ren compares to the status quo](#how-ren-compares-to-the-status-quo) Choosing an agent platform means understanding what each one actually gives you, and where the seams show. Most “AI agent” products solve a narrow slice of the problem. Here’s how Ren stacks up against common alternatives, feature by feature. | | Ren | Claude Managed Agents | ChatGPT Workspace | Manus | Viktor | | --------------------------------- | --- | --------------------- | ----------------- | ------- | ------------------------- | | Managed sandbox infra | | | Partial | | | | Multiplayer sessions | | | | | | | Vault / credential management | | Partial | Partial | | | | Slack/GitHub/Linear native | | | Slack only | | Slack + 3000 integrations | | Scheduling & webhooks | | | | Partial | | | Multi-agent / societies of agents | | Partial | | Partial | | | Long-running tasks | | | Partial | | | | Model-agnostic | | | | | | | Org-level skill/MCP registry | | | | | | | Session replays | | | | | | Ren * Managed sandbox infra * Multiplayer sessions * Vault / credential management * Slack/GitHub/Linear native * Scheduling & webhooks * Multi-agent / societies of agents * Long-running tasks * Model-agnostic * Org-level skill/MCP registry * Session replays Claude Managed Agents * Managed sandbox infra * Multiplayer sessions * Vault / credential management Partial * Slack/GitHub/Linear native * Scheduling & webhooks * Multi-agent / societies of agents Partial * Long-running tasks * Model-agnostic * Org-level skill/MCP registry * Session replays ChatGPT Workspace * Managed sandbox infra Partial * Multiplayer sessions * Vault / credential management Partial * Slack/GitHub/Linear native Slack only * Scheduling & webhooks * Multi-agent / societies of agents * Long-running tasks Partial * Model-agnostic * Org-level skill/MCP registry * Session replays Manus * Managed sandbox infra * Multiplayer sessions * Vault / credential management * Slack/GitHub/Linear native * Scheduling & webhooks Partial * Multi-agent / societies of agents Partial * Long-running tasks * Model-agnostic * Org-level skill/MCP registry * Session replays Viktor * Managed sandbox infra * Multiplayer sessions * Vault / credential management * Slack/GitHub/Linear native Slack + 3000 integrations * Scheduling & webhooks * Multi-agent / societies of agents * Long-running tasks * Model-agnostic * Org-level skill/MCP registry * Session replays Feature comparison across agent platforms. Check marks indicate first-class support; dashes indicate the feature is absent or requires significant custom work. ### [When each platform makes sense](#when-each-platform-makes-sense) **Ren** is built for teams that need to run agents as reliable infrastructure, not as one-off chat sessions. If you’re deploying agents that touch production code, manage secrets, coordinate across multiple systems, or need to run unattended for hours, Ren provides the full stack: managed compute, credential vaults, multi-agent coordination, and session observability. The trade-off is commitment. Ren is an opinionated platform. If you need a single agent for ad-hoc tasks and don’t care about organizational scale, a simpler tool may be faster to start with. **Claude Managed Agents** offers real managed sandboxes and long-running task execution. It’s a strong choice if your team already lives in the Anthropic ecosystem and only needs Claude models. It’s Claude-only, lacks native third-party integrations and an org-level registry, and doesn’t support multiplayer sessions. **ChatGPT Workspace Agents** brings scheduling and Slack deployment to OpenAI’s agent offering. Agents run on GPT models only, sandbox infrastructure is partial, and there’s no multi-agent coordination, session replays, or org-level registry. **Manus** excels as an autonomous agent for ad-hoc tasks, with real managed sandboxes and long-running work. It stops at organizational infrastructure: no vault, no native integrations, no scheduling/webhooks, no org-level registry. **Viktor** shines as a Slack-native task assistant with a massive integration catalog (3,000+). But it’s a task assistant, not an agent deployment platform: no managed sandboxes, vault, scheduling, multi-agent coordination, replays, or registry. ### [The pattern](#the-pattern) The consistent distinction is between **agent tools** and **agent infrastructure**. Manus and Viktor are capable agent tools. Claude Managed Agents and ChatGPT Workspace Agents add some infrastructure within ecosystem boundaries. Ren is agent infrastructure: the compute, secrets, coordination, observability, and sharing layer that turns individual agents into a reliable organizational capability. ## [The ambition: L5 autonomous companies](#the-ambition-l5-autonomous-companies) Ren’s design is shaped by a longer-term thesis. Today’s AI agents operate at roughly L3 autonomy. They handle well-scoped tasks with human oversight. The trajectory points toward L5: **autonomous companies** where humans set intent and review outcomes, and agents handle entire operational domains. Getting from L3 to L5 isn’t a model problem. It’s an infrastructure problem. An L5 agent needs: * **Reliable compute** that doesn’t disappear when someone closes their laptop. * **Safe credential access** that doesn’t require a human to paste keys. * **Coordination primitives** so multiple agents don’t step on each other. * **Observability** so humans can audit, correct, and trust what agents did. * **Persistence** so an agent can pick up where it left off after a failure. Ren builds these primitives now, not because every team needs L5 today, but because the infrastructure you adopt at L3 determines whether you can reach L5 at all. A chat wrapper won’t scale into an autonomous system. A managed platform will.