# Documentation (/)
# Sim Documentation [#sim-documentation]
Welcome to Sim, the open-source AI workspace where teams build, deploy, and manage AI agents. Create agents visually with the workflow builder, conversationally through Chat, or programmatically with the API — connected to 1,000+ integrations and every major LLM.
## Quick Start [#quick-start]
Learn what you can build with Sim
Build your first agent in 10 minutes
Learn about the building blocks
Explore 1,000+ integrations
## Core Concepts [#core-concepts]
Understand how data flows between blocks
Work with workflow and environment variables
Monitor agent runs and manage costs
Start agents via API, webhooks, or schedules
## Advanced Features [#advanced-features]
Set up workspace roles and permissions
Connect external services with Model Context Protocol
Integrate Sim into your applications
---
# What is Sim? (/academy)
Sim is a unified workspace for **building and operating AI systems**. Everything you make lives in one place, and everything connects.
## The workspace [#the-workspace]
A **workspace** is a collection of shared resources and the workflows that use them.
* **Resources** are your data: [tables](/academy/tables/intro) (structured records), [knowledge bases](/academy/knowledge-bases/intro) (searchable memory), and [files](/academy/files/intro) (documents and media).
* **Workflows** are your processes: the agents and automations that read those resources, act, and write results back.
Everything in a workspace can see everything else in it. A workflow reads a table, searches a knowledge base, produces a file, and the next workflow picks up where it left off.
## Integrations connect you to the outside world [#integrations-connect-you-to-the-outside-world]
**Integrations** are plugins. They let your resources and workflows reach services beyond Sim, send a Slack message, read a Gmail inbox, write a row to a CRM, call any API. You connect an account once, and any workflow can use it.
So the whole picture is small: a workspace is **data + processes**, integrations plug it into **everything else**, and the rest of this course is just learning each piece and watching them compose.
## Related documentation [#related-documentation]
* [Introduction](/introduction)
* [Getting started](/getting-started)
---
# Choosing what to use (/agents/choosing)
When you build an agent, several features overlap: a deterministic block and an agent tool can run the same integration, and a custom tool, an MCP tool, and a workflow-as-tool can all give an agent the same action. This page lays out the differences so you pick the right one. They vary along three lines: whether the action is **deterministic** (always runs) or **model-decided** (an agent chooses), whether it lives in one workflow or is **reusable** across your workspace, and whether it comes from Sim or an **external** provider.
The running example is a workflow that scores inbound sales leads. It reads a new lead, enriches it, decides on a score, logs the result, and notifies the team. Each option below builds part of it:
{/* VISUAL: decision tree. Always happens? → deterministic block. Else agent chooses? → agent tool. Reuse across workspace? → custom tool. External toolset? → MCP. Whole workflow? → workflow-as-tool. Reusable instructions? → skill. */}
## Deterministic block [#deterministic-block]
A **block** is a single step that runs at a fixed point on the path, with no model deciding whether to. It always runs when the workflow reaches it. Use one when the action must happen every time: an API call, a data transform, a branch.
In the lead scorer, a [Google Sheets](/integrations) block always appends the scored lead to a tracking sheet, and a [Function](/workflows/blocks/function) block always reshapes the enrichment response into the fields the next step expects. There is no judgment call. The work is guaranteed.
Most steps in a workflow are blocks. Reach for the kinds below only when you want a model to decide, or you want to reuse something.
## Agent tool [#agent-tool]
An **agent tool** is an action you hand to an [Agent](/workflows/blocks/agent) block. The agent reads the task and decides whether and when to call it. The same catalog of [integrations](/integrations) that exist as standalone blocks can also be attached to an agent as tools.
In the lead scorer, the Agent has a Search tool and a Send Email tool. For a lead with a thin profile it runs Search to gather context; for a strong lead it calls Send Email. A thin, obvious lead might trigger neither. The agent chooses per run.
Each tool carries a `usageControl` setting. **Auto** lets the model decide (the default). **Force** makes the agent call the tool every run, for actions that should never be skipped, like always logging the decision. **None** removes the tool from that agent.
A block and an agent tool can be the same underlying integration. The difference is who decides. A block runs because the path reached it. An agent tool runs because the agent chose it.
## Custom tool [#custom-tool]
A **custom tool** is a tool you define once with an object schema and a snippet of JavaScript or Python, then reuse across your workspace. It needs no external account. Use one when you have logic that several agents or workflows would otherwise duplicate.
In the lead scorer, a `normalizeCompanyDomain` custom tool cleans a raw website into a canonical domain. The same tool serves the lead scorer, a deduplication workflow, and a reporting agent. Define it in the workspace, then pick it from any Agent block's tool list.
## MCP server [#mcp-server]
**MCP** (Model Context Protocol) is a standard for connecting an external tool provider. Connect an [MCP server](/agents/mcp) and its tools appear in the agent's tool list as a set. Use it to bring in a complete toolset that Sim does not provide natively, rather than wiring each action by hand.
In the lead scorer, your CRM vendor ships an MCP server. After you connect it once, the agent can read accounts and update records through the vendor's own tools. The difference from a custom tool is who maintains it: a custom tool is code you wrote, while an MCP server is a toolbox someone else maintains.
## Workflow-as-tool [#workflow-as-tool]
A **workflow-as-tool** is a whole workflow handed to an agent as one callable tool. You pick the workflow in the [Agent](/workflows/blocks/agent) block's tool list; the agent decides when to call it and supplies the inputs, which arrive at the child's [Start](/workflows/triggers/start) trigger, and the child's result comes back as the tool's output. Use it when a multi-step procedure should be at the agent's disposal, not on the path.
In the lead scorer, the agent has a `Deep Enrich` workflow as a tool — its own five-step procedure. For a thin lead, the agent calls it to fill out the profile before scoring; for a complete lead, it never runs. The agent weighs a whole procedure the same way it weighs a single action.
A workflow can also run as a fixed step: the [Workflow](/workflows/blocks/workflow) block calls a child workflow because the path reached it. Same child workflow, same Start trigger — the difference, as with blocks and agent tools, is who decides. The Enrich step in the diagram is that deterministic case.
## Skill [#skill]
A **skill** is reusable instructions, a written playbook an agent can follow. Each skill has a short name and description that are always visible to the agent, plus a longer body the agent loads only when it decides the skill applies. Use one to capture how something should be done, separate from the tools that do it.
In the lead scorer, a `lead-scoring-rubric` skill spells out the bands and disqualifiers. The agent sees the skill's name and description on every run, and when a lead is ambiguous it loads the full rubric and applies it. The distinction is simple: a tool is an action the agent takes, and a skill is guidance the agent reads. Manage skills in your [workspace](/agents/skills).
| | Who decides it runs | Where it lives | How you author it |
| -------------------- | ------------------- | ------------------ | --------------------------------------- |
| **Block** | The path | The workflow | Drag in and configure |
| **Agent tool** | The agent | On the Agent block | Pick from the integrations |
| **Custom tool** | The agent | The workspace | Write the code once |
| **MCP server** | The agent | An external server | Connect it |
| **Workflow-as-tool** | The agent | Its own workflow | Build it, then pick it in the tool list |
| **Skill** | The agent | The workspace | Write the instructions |
## Putting it together [#putting-it-together]
The lead scorer uses six kinds at once: blocks for the steps that must always run, agent tools for the calls the model should weigh, a custom tool for shared logic, an MCP server for the CRM, a deep-enrichment workflow the agent calls when a lead needs it, and a skill for the scoring rules. In general, start with a block, then move to an agent tool when a model should decide. Reach for the rest only when you need reuse, an external toolset, a sub-workflow, or written guidance.
## Next [#next]
---
# Custom Tools (/agents/custom-tools)
Custom tools let you write your own JavaScript functions and make them available as callable tools in Agent blocks. This is useful when you need functionality that isn't covered by Sim's built-in integrations — for example, calling an internal API, performing a custom calculation, or transforming data in a specific way.
## How Custom Tools Work [#how-custom-tools-work]
A custom tool has two parts:
1. **Schema** — A JSON definition describing the tool's name, description, and parameters (using the OpenAI function-calling format). This tells the AI agent what the tool does and what inputs it expects.
2. **Code** — A JavaScript function body that runs when the agent calls the tool. Parameters defined in the schema are available as variables in your code.
When an Agent block has access to a custom tool, the AI model decides when to call it based on the schema description and the conversation context — just like built-in tools.
## Creating a Custom Tool [#creating-a-custom-tool]
### Open Custom Tools settings [#open-custom-tools-settings]
Navigate to **Settings → Custom Tools** in your workspace and click **Add**.
### Define the schema [#define-the-schema]
In the **Schema** tab, define your tool using JSON in the OpenAI function-calling format:
```json
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units"
}
},
"required": ["city"]
}
}
}
```
You can use the AI wand button to generate a schema from a natural language description of what the tool should do.
### Write the code [#write-the-code]
Switch to the **Code** tab and write the JavaScript function body. Parameters from your schema are available directly as variables:
```javascript
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units === 'celsius' ? 'metric' : 'imperial'}&appid={{OPENWEATHER_API_KEY}}`
);
const data = await response.json();
return {
temperature: data.main.temp,
description: data.weather[0].description,
humidity: data.main.humidity
};
```
For a secret used as a complete JavaScript expression, prefer the unquoted form, such as `const apiKey = {{OPENWEATHER_API_KEY}};`. Quoted and embedded forms remain supported, including the placeholder embedded in the URL above, `"Bearer {{KEY}}"`, template literals, and JavaScript regex literals. The value is bound separately when the tool executes rather than pasted into its source, so its exact string contents are preserved.
You can also use the AI wand to generate code from a description. Environment variables are referenced with `{{KEY}}` syntax.
### Save [#save]
Click **Save** to create the tool. It's now available to use in any Agent block across your workspace.
## Using Custom Tools in Workflows [#using-custom-tools-in-workflows]
Once created, custom tools appear alongside built-in tools when configuring an Agent block:
1. Open an Agent block
2. Click **Add Tools**
3. Find your custom tool in the tool list
4. The agent will call the tool when it determines it's relevant to the task
## Code Environment [#code-environment]
### Available Features [#available-features]
* **Async/await** — Your code runs in an async context, so you can use `await` directly
* **fetch()** — Make HTTP requests to external APIs
* **Node.js built-ins** — Access to `crypto`, `Buffer`, and other standard modules
* **Environment variables** — Use `{{KEY}}` syntax to bind secrets at execution time without placing plaintext in source code
### Limitations [#limitations]
* **No npm packages** — External libraries like `axios` or `lodash` are not available. Use built-in APIs instead
* **Parameters by name** — Schema parameters are available directly as variables (e.g., `city`), not via a `params` object
### Returning Results [#returning-results]
Return a value from your code to send it back to the agent:
```javascript
const result = await fetch(`https://api.example.com/data?q=${query}`);
const data = await result.json();
return data;
```
The returned value becomes the tool output that the agent sees and can use in its response.
## Managing Custom Tools [#managing-custom-tools]
From **Settings → Custom Tools** you can:
* **Search** tools by name, function name, or description
* **Edit** any tool's schema or code
* **Delete** tools that are no longer needed
Deleting a custom tool removes it from all Agent blocks that reference it. Make sure no active workflows depend on the tool before deleting.
## Permissions [#permissions]
| Action | Required Permission |
| -------------------- | --------------------------------- |
| View custom tools | **Read**, **Write**, or **Admin** |
| Create or edit tools | **Write** or **Admin** |
| Delete tools | **Admin** |
---
# Overview (/agents)
An **agent** is a [workflow](/workflows) that reasons and acts on its own. It reads an input, decides what to do, and carries it out, calling tools and using your data along the way. You build a custom agent in Sim by composing a workflow whose thinking runs through one or more [Agent blocks](/workflows/blocks/agent).
An **Agent block** is the reasoning step inside that workflow: a model reads the values available to it, decides, and returns a result that later blocks read by reference. A simple agent is a single Agent block; a larger one wires several together with other blocks. The Agent block is where the model thinks; the rest of the workflow is what it acts on and through.
The example throughout is an agent that scores inbound sales leads.
## The Agent block [#the-agent-block]
You set up the reasoning step by giving the Agent block a **model** and a **prompt**. The model is the LLM that powers it; you pick one from the available providers, and the default is `claude-sonnet-4-6`. The prompt is a system message that defines who the agent is and how it should behave, plus a user message that carries the input, usually a reference like ``.
When it runs, the Agent block reasons, calls any tools it needs, and stores its result under its own name. By default that result is free text in `content`, read by a later block as ``, alongside run details like the model used, token counts, tool calls, and cost. Every setting and output field is in the [Agent block reference](/workflows/blocks/agent).
## What you give an agent [#what-you-give-an-agent]
On its own, an Agent block can only reason and write text. You extend it so it can act, follow your rules, use your data, remember, and return results other blocks can rely on. Each feature maps to something you'd want an agent to do.
### Take an action: tools [#take-an-action-tools]
To let an agent do something in the world, give it **tools**. A tool is an action the agent can call, like sending an email, searching the web, updating a CRM record, or running another workflow. You attach tools to the Agent block, and the agent decides which to call for the task in front of it. In the lead scorer, the agent has a search tool to gather context on a thin profile and an email tool to reach out to a strong lead.
Tools come from a few places:
* **[Integrations](/integrations)** are the catalog of external services: Gmail, Slack, Airtable, Linear, and hundreds more.
* **[Custom tools](/agents/custom-tools)** are tools you define once with a schema and a snippet of code, then reuse.
* **[MCP tools](/agents/mcp)** come from an external provider you connect through the Model Context Protocol.
* **[Workflow-as-tool](/workflows)** makes another workflow callable, so the agent runs a whole procedure as one step.
The same integration can run two ways. As a [block](/workflows#blocks) it runs because the path reached it. As an agent tool it runs because the agent chose it. Per-tool usage controls (force a tool, or disable one) are in the [Agent block reference](/workflows/blocks/agent).
### Follow a procedure: skills [#follow-a-procedure-skills]
To give an agent instructions it can follow, write a [skill](/agents/skills). A skill is a reusable playbook with a short name and description the agent always sees, plus a longer body it loads only when the skill applies. In the lead scorer, a `lead-scoring-rubric` skill spells out the bands and disqualifiers, and the agent reads the full rubric only when a lead is ambiguous. A tool is an action the agent takes; a skill is guidance it reads.
### Use your documents: knowledge [#use-your-documents-knowledge]
To let an agent answer from your own content, connect a [knowledge base](/knowledgebase). The agent searches it and grounds its answers in what it finds, instead of relying only on the model's general training. Give the lead scorer a knowledge base of past deals and it can compare a new lead against ones you've closed before.
### Remember across runs: memory [#remember-across-runs-memory]
To let an agent reuse information from one run to the next, give it [memory](/integrations/memory), which stores and recalls values keyed to a conversation. Without it, each run starts fresh; with it, an agent in a chat carries what was said earlier into later messages.
### Return a usable result: structured output [#return-a-usable-result-structured-output]
To make an agent's result something later blocks can act on, give it a **structured output**: a typed object you define instead of free text. In the lead scorer, the agent returns `{ score, tier, reason }`, and a later [Condition](/workflows/blocks/condition) block reads `` to branch. See [how blocks pass data](/workflows/data-flow) for reading fields.
## Choosing what to use [#choosing-what-to-use]
Start with one Agent block and a prompt, then add only what the task needs: a tool when the agent should act, a skill when it needs written guidance, a knowledge base when it should answer from your documents, memory when it should remember, and a structured output when a later block has to read its result.
## Next [#next]
---
# Using MCP tools (/agents/mcp)
The Model Context Protocol ([MCP](https://modelcontextprotocol.com/)) is an open standard for connecting AI to external tools and data. Add an MCP server to your workspace and its tools become available to your agents — a way to integrate services Sim doesn't have a built-in integration for.
## Adding an MCP Server as a Tool [#adding-an-mcp-server-as-a-tool]
MCP servers provide collections of tools that your agents can use.
To add one:
1. Navigate to **Settings → MCP Tools**
2. Click **Add** to open the configuration modal
3. Enter a **Server Name** and **Server URL**
4. Add any required **Headers** (e.g. API keys)
5. Click **Add MCP** to save
You can also configure MCP servers directly from the toolbar in an Agent block for quick setup.
### Server Configuration Options [#server-configuration-options]
| Field | Description |
| ------------- | ---------------------------------------------------- |
| **Name** | Display name for the server |
| **URL** | The MCP server endpoint |
| **Transport** | Currently supports `streamable-http` |
| **Headers** | Key-value pairs for authentication or custom headers |
| **Timeout** | Connection timeout in milliseconds (default: 30,000) |
### Environment Variables in Configuration [#environment-variables-in-configuration]
Server URLs and headers support environment variable substitution using `{{VAR_NAME}}` syntax. This keeps sensitive values like API keys out of the server configuration.
```
URL: https://api.example.com/mcp
Authorization: Bearer {{MCP_API_TOKEN}}
```
When you type `{{` in the URL or header fields, a dropdown appears showing available workspace environment variables.
When a saved secret is successfully substituted this way, exact occurrences of its value are masked in stored MCP tool-call traces. The real URL or header value still reaches the MCP server unchanged. See [Execution log protection](/platform/credentials#execution-log-protection) for the exact scope and limitations.
### Testing and Validation [#testing-and-validation]
Click **Test Connection** before saving to verify the server is reachable and discover available tools. The test response shows the number of tools found and the protocol version.
After saving, each server displays its available tools with parameter names, types, and required flags. If a server's tools change (e.g., after a server update), click **Refresh** to fetch the latest schemas. This automatically updates any agent blocks using those tools.
Tool validation badges appear on servers with issues — for example, if a tool was removed from the server but is still referenced in a workflow. Click the badge to see which workflows are affected.
### Domain Allowlisting [#domain-allowlisting]
Self-hosted deployments can restrict which MCP server domains are allowed by setting the `ALLOWED_MCP_DOMAINS` environment variable (comma-separated list). When set, only servers on approved domains can be added. When unset, all domains are allowed.
## Using MCP Tools in Agents [#using-mcp-tools-in-agents]
Once MCP servers are configured, their tools become available within your agent blocks:
1. Open an **Agent** block
2. In the **Tools** section, click **Add tool…**
3. Under **MCP Servers**, click a server to see its tools
4. Select individual tools, or choose **Use all N tools** to add every tool from that server
5. The agent can now access these tools during execution
If you haven't configured a server yet, click **Add MCP Server** at the top of the dropdown to open the setup modal without leaving the block.
## Standalone MCP Tool Block [#standalone-mcp-tool-block]
For more granular control, you can use the dedicated MCP Tool block to execute specific MCP tools:
The MCP Tool block runs one configured tool with parameters you set explicitly, and its output is readable by later blocks like any other.
## When to Use MCP Tool vs Agent [#when-to-use-mcp-tool-vs-agent]
| | **Agent with MCP tools** | **MCP Tool block** |
| -------------- | -------------------------------- | -------------------------------------- |
| **Execution** | AI decides which tools to call | Deterministic — runs the tool you pick |
| **Parameters** | AI chooses at runtime | You set them explicitly |
| **Best for** | Dynamic, conversational flows | Structured, repeatable steps |
| **Reasoning** | Handles complex multi-step logic | One tool, one call |
## Permission Requirements [#permission-requirements]
MCP functionality requires specific workspace permissions:
| Action | Required Permission |
| ---------------------------- | --------------------------------- |
| Create or update MCP servers | **Write** or **Admin** |
| Delete MCP servers | **Admin** |
| Use MCP tools in agents | **Write** or **Admin** |
| View available MCP tools | **Read**, **Write**, or **Admin** |
| Execute MCP Tool blocks | **Read**, **Write**, or **Admin** |
MCP servers run with the permissions of the user who configured them — only connect servers you trust, and review a server's tools before handing them to agents.
---
# Agent skills (/agents/skills)
Agent Skills are reusable packages of instructions that give your AI agents specialized capabilities. Based on the open [Agent Skills](https://agentskills.io) format, skills let you capture domain expertise, workflows, and best practices that agents can load on demand.
## How Skills Work [#how-skills-work]
Skills use **progressive disclosure** to keep agent context lean:
1. **Discovery** — Only skill names and descriptions are included in the agent's system prompt (\~50-100 tokens each)
2. **Activation** — When the agent decides a skill is relevant, it calls the `load_skill` tool to load the full instructions into context
3. **Execution** — The agent follows the loaded instructions to complete the task
## Creating Skills [#creating-skills]
Skills live on the **Integrations** page: click **Integrations** in the workspace sidebar, then switch to the **Skills** tab. It lists every skill in the workspace, searchable by name. Click a skill to open its detail page, where you edit, share, and delete it.
Click **+ Add to Sim** to open the skill create page, which takes three fields:
| Field | Description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | A kebab-case identifier (e.g. `sql-expert`, `code-reviewer`). Max 64 characters. |
| **Description** | A short explanation of what the skill does and when to use it. This is what the agent reads to decide whether to activate the skill. Max 1024 characters. |
| **Content** | The full skill instructions in markdown. This is loaded when the agent activates the skill. |
The description is critical — it's the only thing the agent sees before deciding to load a skill. Be specific about when and why the skill should be used.
### Importing skills [#importing-skills]
Bring in an existing skill in the open [SKILL.md](https://agentskills.io/specification) format two ways:
* **Import** — the **Import** action on the create page takes a `.md` file with YAML frontmatter, or a `.zip` containing a `SKILL.md`.
* **Paste content** — paste the `SKILL.md` straight into **Content**. The frontmatter carries the `name` and `description`; the markdown body is the content.
Integration pages suggest **curated skills** for their service — open one (HubSpot, for example) and add a suggested skill with one click.
### Writing Good Skill Content [#writing-good-skill-content]
Skill content follows the same conventions as [SKILL.md files](https://agentskills.io/specification):
```markdown
# SQL Expert
## When to use this skill
Use when the user asks you to write, optimize, or debug SQL queries.
## Instructions
1. Always ask which database engine (PostgreSQL, MySQL, SQLite)
2. Use CTEs over subqueries for readability
3. Add index recommendations when relevant
4. Explain query plans for optimization requests
## Common Patterns
...
```
**Recommended structure:**
* **When to use** — Specific triggers and scenarios
* **Instructions** — Step-by-step guidance with numbered lists
* **Examples** — Input/output samples showing expected behavior
* **Common Patterns** — Reusable approaches for frequent tasks
* **Edge Cases** — Gotchas and special considerations
Keep skills focused and under 500 lines. If a skill grows too large, split it into multiple specialized skills.
## Skill Editors [#skill-editors]
Everyone in the workspace sees and uses every skill — including members who join later. Nobody needs to be added to a skill to use it.
Each skill has an explicit **editors** list. Editors can edit the skill, delete it, and manage the editors list. Workspace admins can always do this too — they are editors of every skill automatically and cannot be removed from the list. Whoever creates a skill becomes an editor.
Open a skill from the Skills tab to manage it. The detail page has the editable fields, a **Share** action for adding editors from your workspace members, and the **Skill Editors** list at the bottom.
The editors list controls who can edit a skill — it never affects who can see, use, or run it. A workflow that references a skill always executes it, no matter who runs the workflow. Treat skill content as shared team instructions, not as a secret.
## Using Skills in Chat [#using-skills-in-chat]
Skills work in Chat too. Type `/` in the message box to open the skills menu, then pick a skill — or keep typing to filter by name. The skill appears in your message as a tag, e.g. `/format-markdown`.
Tagging a skill loads its full instructions into the conversation, so Sim follows them for that request — no waiting for Sim to decide the skill is relevant on its own.
## Adding Skills to an Agent [#adding-skills-to-an-agent]
Open any **Agent** block and find the **Skills** dropdown below the tools section. Select the skills you want the agent to have access to.
Selected skills appear as cards that you can click to edit or remove.
### What Happens at Runtime [#what-happens-at-runtime]
When the workflow runs:
1. The agent's system prompt includes an `` section listing each skill's name and description
2. A `load_skill` tool is automatically added to the agent's available tools
3. When the agent determines a skill is relevant to the current task, it calls `load_skill` with the skill name
4. The full skill content is returned as a tool response, giving the agent detailed instructions
This works across all supported LLM providers — the `load_skill` tool uses standard tool-calling, so no provider-specific configuration is needed.
## Common Use Cases [#common-use-cases]
Skills are most valuable when agents need specialized knowledge or multi-step workflows:
**Domain Expertise**
* `api-integration-expert` — Best practices for calling specific APIs (authentication, rate limiting, error handling)
* `data-transformation` — ETL patterns, data cleaning, and validation rules
* `code-reviewer` — Code review guidelines specific to your team's standards
**Workflow Templates**
* `bug-investigation` — Step-by-step debugging methodology (reproduce → isolate → test → fix)
* `feature-implementation` — Development workflow from requirements to deployment
* `document-generator` — Templates and formatting rules for technical documentation
**Company-Specific Knowledge**
* `our-architecture` — System architecture diagrams, service dependencies, and deployment processes
* `style-guide` — Brand guidelines, writing tone, UI/UX patterns
* `customer-onboarding` — Standard procedures and common customer questions
**When to use skills vs. agent instructions:**
* Use **skills** for knowledge that applies across multiple workflows or changes frequently
* Use **agent instructions** for task-specific context that's unique to a single agent
## Best Practices [#best-practices]
**Writing Effective Descriptions**
* **Be specific and keyword-rich** — Instead of "Helps with SQL", write "Write optimized SQL queries for PostgreSQL, MySQL, and SQLite, including index recommendations and query plan analysis"
* **Include activation triggers** — Mention specific words or phrases that should prompt the skill (e.g., "Use when the user mentions PDFs, forms, or document extraction")
* **Keep it under 200 words** — Agents scan descriptions quickly; make every word count
**Skill Scope and Organization**
* **One skill per domain** — A focused `sql-expert` skill works better than a broad `database-everything` skill
* **Limit to 5-10 skills per agent** — More skills = more decision overhead; start small and add as needed
* **Split large skills** — If a skill exceeds 500 lines, break it into focused sub-skills
**Content Structure**
* **Use markdown formatting** — Headers, lists, and code blocks help agents parse and follow instructions
* **Provide examples** — Show input/output pairs so agents understand expected behavior
* **Be explicit about edge cases** — Don't assume agents will infer special handling
**Testing and Iteration**
* **Test activation** — Run your workflow and verify the agent loads the skill when expected
* **Check for false positives** — Make sure skills aren't activating when they shouldn't
* **Refine descriptions** — If a skill isn't loading when needed, add more keywords to the description
## Learn More [#learn-more]
* [Agent Skills specification](https://agentskills.io) — The open format for portable agent skills
* [Example skills](https://github.com/anthropics/skills) — Browse community skill examples
* [Best practices](https://agentskills.io/what-are-skills) — Writing effective skills
---
# Authentication (/api-reference/authentication)
To access the Sim API, you need an API key. Sim supports two types of API keys — **personal keys** and **workspace keys** — each with different billing and access behaviors.
## Key Types [#key-types]
| | **Personal Keys** | **Workspace Keys** |
| --------------- | ------------------------------------------ | --------------------------- |
| **Billing** | Workspace payer for workspace-hosted usage | Workspace payer |
| **Scope** | Across workspaces you have access to | Shared across the workspace |
| **Managed by** | Each user individually | Workspace admins |
| **Permissions** | Must be enabled at workspace level | Require admin permissions |
Personal keys identify the user making a request; they do not select who pays.
Hosted usage is billed to the workspace's organization or personal billing
account and, for organizations, is attributed to the actor's member cap.
Workspace admins can disable personal API key usage for their workspace. If
disabled, only workspace keys can be used.
## Generating API Keys [#generating-api-keys]
To generate a personal key, open **Account settings** → **Sim API keys**. Workspace
administrators can create shared keys from **Workspace settings** → **Sim API keys**.
API keys are only shown once when generated. Store your key securely — you will not be able to view it again.
## Using API Keys [#using-api-keys]
Pass your API key in the `X-API-Key` header with every request:
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}}'
```
```typescript
const response = await fetch(
'https://www.sim.ai/api/v2/workflows/{workflowId}/execute',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIM_API_KEY!,
},
body: JSON.stringify({ input: {} }),
}
)
```
```python
import requests
response = requests.post(
"https://www.sim.ai/api/v2/workflows/{workflowId}/execute",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["SIM_API_KEY"],
},
json={"input": {}},
)
```
## Where Keys Are Used [#where-keys-are-used]
API keys authenticate access to:
* **Workflow execution** — run deployed workflows via the API
* **Logs API** — query workflow execution logs and metrics
* **MCP servers** — authenticate connections to deployed MCP servers
* **SDKs** — the [Python](/api-reference/python) and [TypeScript](/api-reference/typescript) SDKs use API keys for all operations
## Security [#security]
* Keys use the `sk-sim-` prefix and are encrypted at rest
* Keys can be revoked at any time from the dashboard
* Use environment variables to store keys — never hardcode them in source code
* For browser-based applications, use a backend proxy to avoid exposing keys to the client
Never expose your API key in client-side code. Use a server-side proxy to make authenticated requests on behalf of your frontend.
---
# Getting Started (/api-reference/getting-started)
## Base URL [#base-url]
All API requests are made to:
```
https://www.sim.ai
```
## Quick Start [#quick-start]
### Get your API key [#get-your-api-key]
Go to the Sim platform and navigate to **Settings**, then go to **Sim Keys** and click **Create**. See [Authentication](/api-reference/authentication) for details on key types.
### Find your workflow ID [#find-your-workflow-id]
Open a workflow in the Sim editor. The workflow ID is in the URL:
```
https://www.sim.ai/workspace/{workspaceId}/w/{workflowId}
```
You can also use the [List Workflows](/api-reference/workflows/listWorkflows) endpoint to get all workflow IDs in a workspace.
### Deploy your workflow [#deploy-your-workflow]
A workflow must be deployed before it can be executed via the API. Click the **Deploy** button in the editor toolbar, or use the dashboard to manage deployments.
### Make your first request [#make-your-first-request]
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}}'
```
```typescript
const response = await fetch(
`https://www.sim.ai/api/v2/workflows/${workflowId}/execute`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIM_API_KEY!,
},
body: JSON.stringify({ input: {} }),
}
)
const data = await response.json()
console.log(data.data.output)
```
```python
import requests
import os
response = requests.post(
f"https://www.sim.ai/api/v2/workflows/{workflow_id}/execute",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["SIM_API_KEY"],
},
json={"input": {}},
)
data = response.json()
print(data["data"]["output"])
```
## Sync vs Async Execution [#sync-vs-async-execution]
By default, workflow executions are **synchronous** — the API blocks until the workflow completes and returns the result directly.
For long-running workflows, use **asynchronous execution** by passing `async: true`:
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}, "async": true}'
```
Keyed callers can optionally provide `X-Run-Id: my-run-123` to choose the run ID. Run IDs cannot be reused; a duplicate returns `409`.
This returns immediately with a `runId` and `statusUrl`:
```json
{
"data": {
"runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
"statusUrl": "https://www.sim.ai/api/v2/workflows/{workflowId}/runs/c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74"
}
}
```
Poll the run status endpoint until the status is terminal:
```bash
curl https://www.sim.ai/api/v2/workflows/{workflowId}/runs/{runId}?includeOutput=true \
-H "X-API-Key: YOUR_API_KEY"
```
Execution status transitions follow: `queued` → `running` → `completed`, `failed`, `cancelled`, or `paused`. The `data.output` field is populated for completed executions when `includeOutput=true`.
## Response Format [#response-format]
Successful v2 responses wrap the run resource in `data`:
```json
{
"data": {
"runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
"workflowId": "{workflowId}",
"status": "completed",
"output": { "result": "Hello, world!" },
"error": null,
"durationMs": 842
}
}
```
## Error Handling [#error-handling]
The API uses standard HTTP status codes. v2 errors include a stable code and human-readable message:
```json
{
"error": {
"code": "NOT_FOUND",
"message": "Workflow not found"
}
}
```
| Status | Meaning | What to do |
| ------ | -------------------------- | --------------------------------------------------- |
| `400` | Invalid request parameters | Check the `details` array for specific field errors |
| `401` | Missing or invalid API key | Verify your `X-API-Key` header |
| `403` | Access denied | Check you have permission for this resource |
| `404` | Resource not found | Verify the ID exists and belongs to your workspace |
| `429` | Rate limit exceeded | Wait for the duration in the `Retry-After` header |
### Unrecognized fields are rejected [#unrecognized-fields-are-rejected]
Every v2 endpoint validates the request against its published schema — path parameters, query string, and body — and answers `400` for any field it does not declare. A misspelled parameter is an error rather than a silent no-op, so `?limt=20` fails instead of quietly returning an unbounded list.
This holds for endpoints that declare no query parameters at all. Do not append tracking tags, cache busters, or other extra parameters to a v2 URL; send only what the endpoint documents.
```json
{
"error": {
"code": "BAD_REQUEST",
"message": "Invalid request",
"details": [
{ "code": "unrecognized_keys", "keys": ["limt"], "path": [], "message": "Unrecognized key: \"limt\"" }
]
}
}
```
Use [Get Billing Status](/api-reference/billing/getBillingStatus) to inspect current credit and storage usage.
## Rate Limits [#rate-limits]
Rate limits depend on your subscription plan and apply separately to synchronous and asynchronous executions.
When rate limited, the API returns a `429` response with a `Retry-After` header indicating how many seconds to wait before retrying.
## Pagination [#pagination]
List endpoints (workflows, logs, audit logs) use **cursor-based pagination**:
```bash
# First page
curl "https://www.sim.ai/api/v2/logs?limit=20" \
-H "X-API-Key: YOUR_API_KEY"
# Next page — use the nextCursor from the previous response
curl "https://www.sim.ai/api/v2/logs?limit=20&cursor=abc123" \
-H "X-API-Key: YOUR_API_KEY"
```
The response includes a `nextCursor` field. When `nextCursor` is absent or `null`, you have reached the last page.
---
# Python (/api-reference/python)
The official Python SDK for Sim allows you to execute workflows programmatically from your Python applications using the official Python SDK.
The Python SDK supports Python 3.8+ with async execution support, automatic rate limiting with exponential backoff, and usage tracking.
## Installation [#installation]
Install the SDK using pip:
```bash
pip install simstudio-sdk
```
## Quick Start [#quick-start]
Here's a simple example to get you started:
```python
from simstudio import SimStudioClient
# Initialize the client
client = SimStudioClient(
api_key="your-api-key-here",
base_url="https://sim.ai" # optional, defaults to https://sim.ai
)
# Execute a workflow
try:
result = client.execute_workflow("workflow-id")
print("Workflow executed successfully:", result)
except Exception as error:
print("Workflow execution failed:", error)
```
## API Reference [#api-reference]
### SimStudioClient [#simstudioclient]
#### Constructor [#constructor]
```python
SimStudioClient(api_key: str, base_url: str = "https://sim.ai")
```
**Parameters:**
* `api_key` (str): Your Sim API key
* `base_url` (str, optional): Base URL for the Sim API
#### Methods [#methods]
##### execute\_workflow() [#execute_workflow]
Execute a workflow with optional input data.
```python
result = client.execute_workflow(
"workflow-id",
input={"message": "Hello, world!"},
timeout=30.0 # 30 seconds
)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow to execute
* `input` (dict, optional): Input data to pass to the workflow
* `timeout` (float, optional): Timeout in seconds (default: 30.0)
* `stream` (bool, optional): Enable streaming responses (default: False)
* `selected_outputs` (list\[str], optional): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
* `async_execution` (bool, optional): Execute asynchronously (default: False)
* `execution_timeout_seconds` (int, optional): Optional server-side async execution cap from 1 to 604800 seconds. Requires `async_execution=True` and cannot extend the account policy.
**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
When `async_execution=True`, returns immediately with a `run_id` and `status_url` for polling. Otherwise, waits for completion.
##### get\_workflow\_status() [#get_workflow_status]
Get the status of a workflow (deployment status, etc.).
```python
status = client.get_workflow_status("workflow-id")
print("Is deployed:", status.is_deployed)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow
**Returns:** `WorkflowStatus`
##### validate\_workflow() [#validate_workflow]
Validate that a workflow is ready for execution.
```python
is_ready = client.validate_workflow("workflow-id")
if is_ready:
# Workflow is deployed and ready
pass
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow
**Returns:** `bool`
##### get\_workflow\_run() [#get_workflow_run]
Get the status and optional outputs of a workflow execution.
```python
status = client.get_workflow_run("workflow-id", "run-id", include_output=True)
print("Status:", status["status"]) # 'queued', 'running', 'completed', 'failed'
if status["status"] == "completed":
print("Output:", status["output"])
```
**Parameters:**
* `workflow_id` (str): The workflow ID
* `run_id` (str): The run ID returned from async execution
* `include_output` (bool, optional): Include the final output for completed executions
* `selected_outputs` (list\[str], optional): Block output selectors to include
**Returns:** `Dict[str, Any]`
**Response fields:**
* `runId` (str): The run ID
* `workflowId` (str): The workflow ID
* `status` (str): One of `'queued'`, `'pending'`, `'running'`, `'paused'`, `'completed'`, `'failed'`, `'cancelled'`
* `startedAt` / `endedAt` (str): Execution timestamps
* `durationMs` (int, optional): Duration in milliseconds
* `output` (any, optional): The workflow output when requested for a completed execution
* `blockOutputs` (dict, optional): Requested block outputs
* `error` (dict, optional): Structured failure details with `code`, `message`, and optional `details`
##### get\_job\_status() [#get_job_status]
Get the status of a job created through the legacy async execution endpoint. New integrations should use `get_workflow_run()` with the run ID instead.
```python
status = client.get_job_status("legacy-job-id")
```
##### execute\_with\_retry() [#execute_with_retry]
Execute a workflow with automatic retry on rate limit errors using exponential backoff.
```python
result = client.execute_with_retry(
"workflow-id",
input={"message": "Hello"},
timeout=30.0,
max_retries=3, # Maximum number of retries
initial_delay=1.0, # Initial delay in seconds
max_delay=30.0, # Maximum delay in seconds
backoff_multiplier=2.0 # Exponential backoff multiplier
)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow to execute
* `input` (dict, optional): Input data to pass to the workflow
* `timeout` (float, optional): Timeout in seconds
* `stream` (bool, optional): Enable streaming responses
* `selected_outputs` (list, optional): Block outputs to stream
* `async_execution` (bool, optional): Execute asynchronously
* `max_retries` (int, optional): Maximum number of retries (default: 3)
* `initial_delay` (float, optional): Initial delay in seconds (default: 1.0)
* `max_delay` (float, optional): Maximum delay in seconds (default: 30.0)
* `backoff_multiplier` (float, optional): Backoff multiplier (default: 2.0)
**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
##### get\_rate\_limit\_info() [#get_rate_limit_info]
Get the current rate limit information from the last API response.
```python
rate_limit_info = client.get_rate_limit_info()
if rate_limit_info:
print("Limit:", rate_limit_info.limit)
print("Remaining:", rate_limit_info.remaining)
print("Reset:", datetime.fromtimestamp(rate_limit_info.reset))
```
**Returns:** `RateLimitInfo | None`
##### get\_usage\_limits() [#get_usage_limits]
Get current usage limits and quota information for your account.
```python
limits = client.get_usage_limits()
print("Sync requests remaining:", limits.rate_limit["sync"]["remaining"])
print("Async requests remaining:", limits.rate_limit["async"]["remaining"])
print("Current period cost:", limits.usage["currentPeriodCost"])
print("Plan:", limits.usage["plan"])
```
**Returns:** `UsageLimits`
**Response structure:**
```python
{
"success": bool,
"rateLimit": {
"sync": {
"isLimited": bool,
"limit": int,
"remaining": int,
"resetAt": str
},
"async": {
"isLimited": bool,
"limit": int,
"remaining": int,
"resetAt": str
},
"authType": str # 'api' or 'manual'
},
"usage": {
"currentPeriodCost": float,
"limit": float,
"plan": str # e.g., 'free', 'pro'
}
}
```
##### set\_api\_key() [#set_api_key]
Update the API key.
```python
client.set_api_key("new-api-key")
```
##### set\_base\_url() [#set_base_url]
Update the base URL.
```python
client.set_base_url("https://my-custom-domain.com")
```
##### close() [#close]
Close the underlying HTTP session.
```python
client.close()
```
## Data Classes [#data-classes]
### WorkflowExecutionResult [#workflowexecutionresult]
```python
@dataclass
class WorkflowExecutionResult:
success: bool
output: Optional[Any] = None
error: Optional[str] = None
logs: Optional[List[Any]] = None
metadata: Optional[Dict[str, Any]] = None
trace_spans: Optional[List[Any]] = None
total_duration: Optional[float] = None
status: Optional[str] = None
```
`success` is `True` only for the `completed` and `paused` statuses. `status` carries the server's terminal status verbatim, so a cancelled run (`success=False`, `error=None`) is distinguishable from a failed one.
### AsyncExecutionResult [#asyncexecutionresult]
```python
@dataclass
class AsyncExecutionResult:
success: bool
run_id: str
status_url: str
message: str = ""
async_execution: bool = True
```
### WorkflowStatus [#workflowstatus]
```python
@dataclass
class WorkflowStatus:
is_deployed: bool
deployed_at: Optional[str] = None
needs_redeployment: bool = False
```
### RateLimitInfo [#ratelimitinfo]
```python
@dataclass
class RateLimitInfo:
limit: int
remaining: int
reset: int
retry_after: Optional[int] = None
```
### UsageLimits [#usagelimits]
```python
@dataclass
class UsageLimits:
success: bool
rate_limit: Dict[str, Any]
usage: Dict[str, Any]
```
### SimStudioError [#simstudioerror]
```python
class SimStudioError(Exception):
def __init__(self, message: str, code: Optional[str] = None, status: Optional[int] = None):
super().__init__(message)
self.code = code
self.status = status
```
**Common error codes:**
* `UNAUTHORIZED`: Invalid API key
* `TIMEOUT`: Request timed out
* `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
* `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
* `EXECUTION_ERROR`: Workflow execution failed
## Examples [#examples]
### Basic Workflow Execution [#basic-workflow-execution]
Set up the SimStudioClient with your API key.
Check if the workflow is deployed and ready for execution.
Run the workflow with your input data.
Process the execution result and handle any errors.
```python
import os
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def run_workflow():
try:
# Check if workflow is ready
is_ready = client.validate_workflow("my-workflow-id")
if not is_ready:
raise Exception("Workflow is not deployed or ready")
# Execute the workflow
result = client.execute_workflow(
"my-workflow-id",
input={
"message": "Process this data",
"user_id": "12345"
}
)
if result.success:
print("Output:", result.output)
print("Duration:", result.metadata.get("duration") if result.metadata else None)
else:
print("Workflow failed:", result.error)
except Exception as error:
print("Error:", error)
run_workflow()
```
### Error Handling [#error-handling]
Handle different types of errors that may occur during workflow execution:
```python
from simstudio import SimStudioClient, SimStudioError
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_error_handling():
try:
result = client.execute_workflow("workflow-id")
return result
except SimStudioError as error:
if error.code == "UNAUTHORIZED":
print("Invalid API key")
elif error.code == "TIMEOUT":
print("Workflow execution timed out")
elif error.code == "USAGE_LIMIT_EXCEEDED":
print("Usage limit exceeded")
elif error.code == "INVALID_JSON":
print("Invalid JSON in request body")
else:
print(f"Workflow error: {error}")
raise
except Exception as error:
print(f"Unexpected error: {error}")
raise
```
### Context Manager Usage [#context-manager-usage]
Use the client as a context manager to automatically handle resource cleanup:
```python
from simstudio import SimStudioClient
import os
# Using context manager to automatically close the session
with SimStudioClient(api_key=os.getenv("SIM_API_KEY")) as client:
result = client.execute_workflow("workflow-id")
print("Result:", result)
# Session is automatically closed here
```
### Batch Workflow Execution [#batch-workflow-execution]
Execute multiple workflows efficiently:
```python
from simstudio import SimStudioClient
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_workflows_batch(workflow_data_pairs):
"""Execute multiple workflows with different input data."""
results = []
for workflow_id, input_data in workflow_data_pairs:
try:
# Validate workflow before execution
if not client.validate_workflow(workflow_id):
print(f"Skipping {workflow_id}: not deployed")
continue
result = client.execute_workflow(workflow_id, input_data)
results.append({
"workflow_id": workflow_id,
"success": result.success,
"output": result.output,
"error": result.error
})
except Exception as error:
results.append({
"workflow_id": workflow_id,
"success": False,
"error": str(error)
})
return results
# Example usage
workflows = [
("workflow-1", {"type": "analysis", "data": "sample1"}),
("workflow-2", {"type": "processing", "data": "sample2"}),
]
results = execute_workflows_batch(workflows)
for result in results:
print(f"Workflow {result['workflow_id']}: {'Success' if result['success'] else 'Failed'}")
```
### Async Workflow Execution [#async-workflow-execution]
Execute workflows asynchronously for long-running tasks:
```python
import os
import time
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_async():
try:
# Start async execution
result = client.execute_workflow(
"workflow-id",
input={"data": "large dataset"},
async_execution=True # Execute asynchronously
)
# Check if result is an async execution
if hasattr(result, 'async_execution') and result.async_execution:
print(f"Run ID: {result.run_id}")
print(f"Status endpoint: {result.status_url}")
# Poll for completion
status = client.get_workflow_run(
"workflow-id", result.run_id, include_output=True
)
while status["status"] in ["queued", "pending", "running"]:
print(f"Current status: {status['status']}")
time.sleep(2) # Wait 2 seconds
status = client.get_workflow_run(
"workflow-id", result.run_id, include_output=True
)
if status["status"] == "completed":
print("Workflow completed!")
print(f"Output: {status['output']}")
print(f"Duration: {status['durationMs']}")
else:
print(f"Workflow failed: {status['error']}")
except Exception as error:
print(f"Error: {error}")
execute_async()
```
### Rate Limiting and Retry [#rate-limiting-and-retry]
Handle rate limits automatically with exponential backoff:
```python
import os
from simstudio import SimStudioClient, SimStudioError
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_retry_handling():
try:
# Automatically retries on rate limit
result = client.execute_with_retry(
"workflow-id",
input={"message": "Process this"},
max_retries=5,
initial_delay=1.0,
max_delay=60.0,
backoff_multiplier=2.0
)
print(f"Success: {result}")
except SimStudioError as error:
if error.code == "RATE_LIMIT_EXCEEDED":
print("Rate limit exceeded after all retries")
# Check rate limit info
rate_limit_info = client.get_rate_limit_info()
if rate_limit_info:
from datetime import datetime
reset_time = datetime.fromtimestamp(rate_limit_info.reset)
print(f"Rate limit resets at: {reset_time}")
execute_with_retry_handling()
```
### Usage Monitoring [#usage-monitoring]
Monitor your account usage and limits:
```python
import os
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def check_usage():
try:
limits = client.get_usage_limits()
print("=== Rate Limits ===")
print("Sync requests:")
print(f" Limit: {limits.rate_limit['sync']['limit']}")
print(f" Remaining: {limits.rate_limit['sync']['remaining']}")
print(f" Resets at: {limits.rate_limit['sync']['resetAt']}")
print(f" Is limited: {limits.rate_limit['sync']['isLimited']}")
print("\nAsync requests:")
print(f" Limit: {limits.rate_limit['async']['limit']}")
print(f" Remaining: {limits.rate_limit['async']['remaining']}")
print(f" Resets at: {limits.rate_limit['async']['resetAt']}")
print(f" Is limited: {limits.rate_limit['async']['isLimited']}")
print("\n=== Usage ===")
print(f"Current period cost: ${limits.usage['currentPeriodCost']:.2f}")
print(f"Limit: ${limits.usage['limit']:.2f}")
print(f"Plan: {limits.usage['plan']}")
percent_used = (limits.usage['currentPeriodCost'] / limits.usage['limit']) * 100
print(f"Usage: {percent_used:.1f}%")
if percent_used > 80:
print("⚠️ Warning: You are approaching your usage limit!")
except Exception as error:
print(f"Error checking usage: {error}")
check_usage()
```
### Streaming Workflow Execution [#streaming-workflow-execution]
Execute workflows with real-time streaming responses:
```python
from simstudio import SimStudioClient
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_streaming():
"""Execute workflow with streaming enabled."""
try:
# Enable streaming for specific block outputs
result = client.execute_workflow(
"workflow-id",
input={"message": "Count to five"},
stream=True,
selected_outputs=["agent1.content"] # Use blockName.attribute format
)
print("Workflow result:", result)
except Exception as error:
print("Error:", error)
execute_with_streaming()
```
The streaming response follows the Server-Sent Events (SSE) format:
```
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]
```
**Flask Streaming Example:**
```python
from flask import Flask, Response, stream_with_context
import requests
import json
import os
app = Flask(__name__)
@app.route('/stream-workflow')
def stream_workflow():
"""Stream workflow execution to the client."""
def generate():
response = requests.post(
'https://sim.ai/api/v2/workflows/WORKFLOW_ID/execute',
headers={
'Content-Type': 'application/json',
'X-API-Key': os.getenv('SIM_API_KEY')
},
json={
'input': {'message': 'Generate a story'},
'stream': True,
'selectedOutputs': ['agent1.content']
},
stream=True
)
for line in response.iter_lines():
if line:
decoded_line = line.decode('utf-8')
if decoded_line.startswith('data: '):
data = decoded_line[6:] # Remove 'data: ' prefix
if data == '[DONE]':
break
try:
parsed = json.loads(data)
if 'chunk' in parsed:
yield f"data: {json.dumps(parsed)}\n\n"
elif parsed.get('event') == 'done':
yield f"data: {json.dumps(parsed)}\n\n"
print("Execution complete:", parsed.get('metadata'))
except json.JSONDecodeError:
pass
return Response(
stream_with_context(generate()),
mimetype='text/event-stream'
)
if __name__ == '__main__':
app.run(debug=True)
```
### Environment Configuration [#environment-configuration]
Configure the client using environment variables:
```python
import os
from simstudio import SimStudioClient
# Development configuration
client = SimStudioClient(
api_key=os.getenv("SIM_API_KEY")
base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
)
```
```python
import os
from simstudio import SimStudioClient
# Production configuration with error handling
api_key = os.getenv("SIM_API_KEY")
if not api_key:
raise ValueError("SIM_API_KEY environment variable is required")
client = SimStudioClient(
api_key=api_key,
base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
)
```
## Getting Your API Key [#getting-your-api-key]
Navigate to [Sim](https://sim.ai) and log in to your account.
Navigate to the workflow you want to execute programmatically.
Click on "Deploy" to deploy your workflow if it hasn't been deployed yet.
During the deployment process, select or create an API key.
Copy the API key to use in your Python application.
## Requirements [#requirements]
* Python 3.8+
* requests >= 2.25.0
## License [#license]
Apache-2.0
---
# TypeScript (/api-reference/typescript)
The official TypeScript/JavaScript SDK for Sim provides full type safety and supports both Node.js and browser environments, allowing you to execute workflows programmatically from your Node.js applications, web applications, and other JavaScript environments.
The TypeScript SDK provides full type safety, async execution support, automatic rate limiting with exponential backoff, and usage tracking.
## Installation [#installation]
Install the SDK using your preferred package manager:
```bash
npm install simstudio-ts-sdk
```
```bash
yarn add simstudio-ts-sdk
```
```bash
bun add simstudio-ts-sdk
```
## Quick Start [#quick-start]
Here's a simple example to get you started:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Initialize the client
const client = new SimStudioClient({
apiKey: 'your-api-key-here',
baseUrl: 'https://sim.ai' // optional, defaults to https://sim.ai
});
// Execute a workflow
try {
const result = await client.executeWorkflow('workflow-id');
console.log('Workflow executed successfully:', result);
} catch (error) {
console.error('Workflow execution failed:', error);
}
```
## API Reference [#api-reference]
### SimStudioClient [#simstudioclient]
#### Constructor [#constructor]
```typescript
new SimStudioClient(config: SimStudioConfig)
```
**Configuration:**
* `config.apiKey` (string): Your Sim API key
* `config.baseUrl` (string, optional): Base URL for the Sim API (defaults to `https://sim.ai`)
#### Methods [#methods]
##### executeWorkflow() [#executeworkflow]
Execute a workflow with optional input data.
```typescript
const result = await client.executeWorkflow('workflow-id', { message: 'Hello, world!' }, {
timeout: 30000 // 30 seconds
});
```
**Parameters:**
* `workflowId` (string): The ID of the workflow to execute
* `input` (any, optional): Input data to pass to the workflow
* `options` (ExecutionOptions, optional):
* `timeout` (number): Timeout in milliseconds (default: 30000)
* `stream` (boolean): Enable streaming responses (default: false)
* `selectedOutputs` (string\[]): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
* `async` (boolean): Execute asynchronously (default: false)
* `executionTimeoutSeconds` (number): Optional server-side async execution cap from 1 to 604800 seconds. Requires `async: true` and cannot extend the account policy.
**Returns:** `Promise`
When `async: true`, returns immediately with a `runId` and `statusUrl` for polling. Otherwise, waits for completion.
##### getWorkflowStatus() [#getworkflowstatus]
Get the status of a workflow (deployment status, etc.).
```typescript
const status = await client.getWorkflowStatus('workflow-id');
console.log('Is deployed:', status.isDeployed);
```
**Parameters:**
* `workflowId` (string): The ID of the workflow
**Returns:** `Promise`
##### validateWorkflow() [#validateworkflow]
Validate that a workflow is ready for execution.
```typescript
const isReady = await client.validateWorkflow('workflow-id');
if (isReady) {
// Workflow is deployed and ready
}
```
**Parameters:**
* `workflowId` (string): The ID of the workflow
**Returns:** `Promise`
##### getWorkflowRun() [#getworkflowrun]
Get the status and optional outputs of a workflow run.
```typescript
const status = await client.getWorkflowRun('workflow-id', 'run-id', {
includeOutput: true
});
console.log('Status:', status.status); // 'queued', 'running', 'completed', 'failed'
if (status.status === 'completed') {
console.log('Output:', status.output);
}
```
**Parameters:**
* `workflowId` (string): The workflow ID
* `runId` (string): The run ID returned from async execution
* `options.includeOutput` (boolean, optional): Include the final output for completed executions
* `options.selectedOutputs` (string\[], optional): Block output selectors to include
**Returns:** `Promise`
**Response fields:**
* `runId` (string): The run ID
* `workflowId` (string): The workflow ID
* `status` (string): One of `'queued'`, `'pending'`, `'running'`, `'paused'`, `'completed'`, `'failed'`, `'cancelled'`
* `startedAt` / `endedAt` (string): Execution timestamps
* `durationMs` (number, nullable): Duration in milliseconds
* `output` (any, nullable): The workflow output when requested for a completed execution
* `blockOutputs` (object, nullable): Requested block outputs
* `error` (object, nullable): Structured failure details with `code`, `message`, and optional `details`
##### getJobStatus() [#getjobstatus]
Get the status of a job created through the legacy async execution endpoint. New integrations should use `getWorkflowRun()` with the run ID instead.
```typescript
const status = await client.getJobStatus('legacy-job-id');
```
##### executeWithRetry() [#executewithretry]
Execute a workflow with automatic retry on rate limit errors using exponential backoff.
```typescript
const result = await client.executeWithRetry('workflow-id', { message: 'Hello' }, {
timeout: 30000
}, {
maxRetries: 3, // Maximum number of retries
initialDelay: 1000, // Initial delay in ms (1 second)
maxDelay: 30000, // Maximum delay in ms (30 seconds)
backoffMultiplier: 2 // Exponential backoff multiplier
});
```
**Parameters:**
* `workflowId` (string): The ID of the workflow to execute
* `input` (any, optional): Input data to pass to the workflow
* `options` (ExecutionOptions, optional): Same as `executeWorkflow()`
* `retryOptions` (RetryOptions, optional):
* `maxRetries` (number): Maximum number of retries (default: 3)
* `initialDelay` (number): Initial delay in ms (default: 1000)
* `maxDelay` (number): Maximum delay in ms (default: 30000)
* `backoffMultiplier` (number): Backoff multiplier (default: 2)
**Returns:** `Promise`
The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
##### getRateLimitInfo() [#getratelimitinfo]
Get the current rate limit information from the last API response.
```typescript
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Limit:', rateLimitInfo.limit);
console.log('Remaining:', rateLimitInfo.remaining);
console.log('Reset:', new Date(rateLimitInfo.reset * 1000));
}
```
**Returns:** `RateLimitInfo | null`
##### getUsageLimits() [#getusagelimits]
Get current usage limits and quota information for your account.
```typescript
const limits = await client.getUsageLimits();
console.log('Sync requests remaining:', limits.rateLimit.sync.remaining);
console.log('Async requests remaining:', limits.rateLimit.async.remaining);
console.log('Current period cost:', limits.usage.currentPeriodCost);
console.log('Plan:', limits.usage.plan);
```
**Returns:** `Promise`
**Response structure:**
```typescript
{
success: boolean
rateLimit: {
sync: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
async: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
authType: string // 'api' or 'manual'
}
usage: {
currentPeriodCost: number
limit: number
plan: string // e.g., 'free', 'pro'
}
}
```
##### setApiKey() [#setapikey]
Update the API key.
```typescript
client.setApiKey('new-api-key');
```
##### setBaseUrl() [#setbaseurl]
Update the base URL.
```typescript
client.setBaseUrl('https://my-custom-domain.com');
```
## Types [#types]
### WorkflowExecutionResult [#workflowexecutionresult]
```typescript
interface WorkflowExecutionResult {
success: boolean;
output?: any;
error?: string;
logs?: any[];
metadata?: {
duration?: number;
runId?: string;
[key: string]: any;
};
traceSpans?: any[];
totalDuration?: number;
}
```
### AsyncExecutionResult [#asyncexecutionresult]
```typescript
interface AsyncExecutionResult {
success: boolean;
runId: string;
statusUrl: string;
message: string;
async: true;
}
```
### WorkflowStatus [#workflowstatus]
```typescript
interface WorkflowStatus {
isDeployed: boolean;
deployedAt?: string;
needsRedeployment: boolean;
}
```
### RateLimitInfo [#ratelimitinfo]
```typescript
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number;
retryAfter?: number;
}
```
### UsageLimits [#usagelimits]
```typescript
interface UsageLimits {
success: boolean;
rateLimit: {
sync: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
async: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
authType: string;
};
usage: {
currentPeriodCost: number;
limit: number;
plan: string;
};
}
```
### SimStudioError [#simstudioerror]
```typescript
class SimStudioError extends Error {
code?: string;
status?: number;
}
```
**Common error codes:**
* `UNAUTHORIZED`: Invalid API key
* `TIMEOUT`: Request timed out
* `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
* `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
* `EXECUTION_ERROR`: Workflow execution failed
## Examples [#examples]
### Basic Workflow Execution [#basic-workflow-execution]
Set up the SimStudioClient with your API key.
Check if the workflow is deployed and ready for execution.
Run the workflow with your input data.
Process the execution result and handle any errors.
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function runWorkflow() {
try {
// Check if workflow is ready
const isReady = await client.validateWorkflow('my-workflow-id');
if (!isReady) {
throw new Error('Workflow is not deployed or ready');
}
// Execute the workflow
const result = await client.executeWorkflow('my-workflow-id', {
message: 'Process this data',
userId: '12345'
});
if (result.success) {
console.log('Output:', result.output);
console.log('Duration:', result.metadata?.duration);
} else {
console.error('Workflow failed:', result.error);
}
} catch (error) {
console.error('Error:', error);
}
}
runWorkflow();
```
### Error Handling [#error-handling]
Handle different types of errors that may occur during workflow execution:
```typescript
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithErrorHandling() {
try {
const result = await client.executeWorkflow('workflow-id');
return result;
} catch (error) {
if (error instanceof SimStudioError) {
switch (error.code) {
case 'UNAUTHORIZED':
console.error('Invalid API key');
break;
case 'TIMEOUT':
console.error('Workflow execution timed out');
break;
case 'USAGE_LIMIT_EXCEEDED':
console.error('Usage limit exceeded');
break;
case 'INVALID_JSON':
console.error('Invalid JSON in request body');
break;
default:
console.error('Workflow error:', error.message);
}
} else {
console.error('Unexpected error:', error);
}
throw error;
}
}
```
### Environment Configuration [#environment-configuration]
Configure the client using environment variables:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Development configuration
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL // optional
});
```
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Production configuration with validation
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL || 'https://sim.ai'
});
```
### Node.js Express Integration [#nodejs-express-integration]
Integrate with an Express.js server:
```typescript
import express from 'express';
import { SimStudioClient } from 'simstudio-ts-sdk';
const app = express();
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
app.use(express.json());
app.post('/execute-workflow', async (req, res) => {
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, input, {
timeout: 60000
});
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Workflow execution error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
```
### Next.js API Route [#nextjs-api-route]
Use with Next.js API routes:
```typescript
// pages/api/workflow.ts or app/api/workflow/route.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, input, {
timeout: 30000
});
res.status(200).json(result);
} catch (error) {
console.error('Error executing workflow:', error);
res.status(500).json({
error: 'Failed to execute workflow'
});
}
}
```
### Browser Usage [#browser-usage]
Use in the browser (with proper CORS configuration):
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Note: In production, use a proxy server to avoid exposing API keys
const client = new SimStudioClient({
apiKey: 'your-public-api-key', // Use with caution in browser
baseUrl: 'https://sim.ai'
});
async function executeClientSideWorkflow() {
try {
const result = await client.executeWorkflow('workflow-id', {
userInput: 'Hello from browser'
});
console.log('Workflow result:', result);
// Update UI with result
document.getElementById('result')!.textContent =
JSON.stringify(result.output, null, 2);
} catch (error) {
console.error('Error:', error);
}
}
```
### File Upload [#file-upload]
File objects are automatically detected and converted to base64 format. Include them in your input under the field name matching your workflow's API trigger input format.
The SDK converts File objects to this format:
```typescript
{
type: 'file',
data: 'data:mime/type;base64,base64data',
name: 'filename',
mime: 'mime/type'
}
```
Alternatively, you can manually provide files using the URL format:
```typescript
{
type: 'url',
data: 'https://example.com/file.pdf',
name: 'file.pdf',
mime: 'application/pdf'
}
```
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.NEXT_PUBLIC_SIM_API_KEY!
});
// From file input
async function handleFileUpload(event: Event) {
const input = event.target as HTMLInputElement;
const files = Array.from(input.files || []);
// Include files under the field name from your API trigger's input format
const result = await client.executeWorkflow('workflow-id', {
documents: files, // Must match your workflow's "files" field name
instructions: 'Analyze these documents'
});
console.log('Result:', result);
}
```
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
import fs from 'fs';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
// Read file and create File object
const fileBuffer = fs.readFileSync('./document.pdf');
const file = new File([fileBuffer], 'document.pdf', {
type: 'application/pdf'
});
// Include files under the field name from your API trigger's input format
const result = await client.executeWorkflow('workflow-id', {
documents: [file], // Must match your workflow's "files" field name
query: 'Summarize this document'
});
```
When using the SDK in the browser, be careful not to expose sensitive API keys. Consider using a backend proxy or public API keys with limited permissions.
### React Hook Example [#react-hook-example]
Create a custom React hook for workflow execution:
```typescript
import { useState, useCallback } from 'react';
import { SimStudioClient, WorkflowExecutionResult } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
interface UseWorkflowResult {
result: WorkflowExecutionResult | null;
loading: boolean;
error: Error | null;
executeWorkflow: (workflowId: string, input?: any) => Promise;
}
export function useWorkflow(): UseWorkflowResult {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const executeWorkflow = useCallback(async (workflowId: string, input?: any) => {
setLoading(true);
setError(null);
setResult(null);
try {
const workflowResult = await client.executeWorkflow(workflowId, input, {
timeout: 30000
});
setResult(workflowResult);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
}, []);
return {
result,
loading,
error,
executeWorkflow
};
}
// Usage in component
function WorkflowComponent() {
const { result, loading, error, executeWorkflow } = useWorkflow();
const handleExecute = () => {
executeWorkflow('my-workflow-id', {
message: 'Hello from React!'
});
};
return (
{error &&
Error: {error.message}
}
{result && (
Result:
{JSON.stringify(result, null, 2)}
)}
);
}
```
### Async Workflow Execution [#async-workflow-execution]
Execute workflows asynchronously for long-running tasks:
```typescript
import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeAsync() {
try {
// Start async execution
const result = await client.executeWorkflow('workflow-id', { data: 'large dataset' }, {
async: true // Execute asynchronously
});
// Check if result is an async execution
if ('async' in result && result.async) {
console.log('Run ID:', result.runId);
console.log('Status endpoint:', result.statusUrl);
// Poll for completion
let status = await client.getWorkflowRun('workflow-id', result.runId, {
includeOutput: true
});
while (status.status === 'queued' || status.status === 'pending' || status.status === 'running') {
console.log('Current status:', status.status);
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
status = await client.getWorkflowRun('workflow-id', result.runId, {
includeOutput: true
});
}
if (status.status === 'completed') {
console.log('Workflow completed!');
console.log('Output:', status.output);
console.log('Duration:', status.durationMs);
} else {
console.error('Workflow failed:', status.error);
}
}
} catch (error) {
console.error('Error:', error);
}
}
executeAsync();
```
### Rate Limiting and Retry [#rate-limiting-and-retry]
Handle rate limits automatically with exponential backoff:
```typescript
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithRetryHandling() {
try {
// Automatically retries on rate limit
const result = await client.executeWithRetry('workflow-id', { message: 'Process this' }, {}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
backoffMultiplier: 2
});
console.log('Success:', result);
} catch (error) {
if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Rate limit exceeded after all retries');
// Check rate limit info
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000));
}
}
}
}
```
### Usage Monitoring [#usage-monitoring]
Monitor your account usage and limits:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function checkUsage() {
try {
const limits = await client.getUsageLimits();
console.log('=== Rate Limits ===');
console.log('Sync requests:');
console.log(' Limit:', limits.rateLimit.sync.limit);
console.log(' Remaining:', limits.rateLimit.sync.remaining);
console.log(' Resets at:', limits.rateLimit.sync.resetAt);
console.log(' Is limited:', limits.rateLimit.sync.isLimited);
console.log('\nAsync requests:');
console.log(' Limit:', limits.rateLimit.async.limit);
console.log(' Remaining:', limits.rateLimit.async.remaining);
console.log(' Resets at:', limits.rateLimit.async.resetAt);
console.log(' Is limited:', limits.rateLimit.async.isLimited);
console.log('\n=== Usage ===');
console.log('Current period cost: $' + limits.usage.currentPeriodCost.toFixed(2));
console.log('Limit: $' + limits.usage.limit.toFixed(2));
console.log('Plan:', limits.usage.plan);
const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100;
console.log('Usage: ' + percentUsed.toFixed(1) + '%');
if (percentUsed > 80) {
console.warn('⚠️ Warning: You are approaching your usage limit!');
}
} catch (error) {
console.error('Error checking usage:', error);
}
}
checkUsage();
```
### Streaming Workflow Execution [#streaming-workflow-execution]
Execute workflows with real-time streaming responses:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithStreaming() {
try {
// Enable streaming for specific block outputs
const result = await client.executeWorkflow('workflow-id', { message: 'Count to five' }, {
stream: true,
selectedOutputs: ['agent1.content'] // Use blockName.attribute format
});
console.log('Workflow result:', result);
} catch (error) {
console.error('Error:', error);
}
}
```
The streaming response follows the Server-Sent Events (SSE) format:
```
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]
```
**React Streaming Example:**
```typescript
import { useState, useEffect } from 'react';
function StreamingWorkflow() {
const [output, setOutput] = useState('');
const [loading, setLoading] = useState(false);
const executeStreaming = async () => {
setLoading(true);
setOutput('');
// IMPORTANT: Make this API call from your backend server, not the browser
// Never expose your API key in client-side code
const response = await fetch('https://sim.ai/api/v2/workflows/WORKFLOW_ID/execute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIM_API_KEY! // Server-side environment variable only
},
body: JSON.stringify({
input: { message: 'Generate a story' },
stream: true,
selectedOutputs: ['agent1.content']
})
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (reader) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
setLoading(false);
break;
}
try {
const parsed = JSON.parse(data);
if (parsed.chunk) {
setOutput(prev => prev + parsed.chunk);
} else if (parsed.event === 'done') {
console.log('Execution complete:', parsed.metadata);
}
} catch (e) {
// Skip invalid JSON
}
}
}
}
};
return (
{output}
);
}
```
## Getting Your API Key [#getting-your-api-key]
Navigate to [Sim](https://sim.ai) and log in to your account.
Navigate to the workflow you want to execute programmatically.
Click on "Deploy" to deploy your workflow if it hasn't been deployed yet.
During the deployment process, select or create an API key.
Copy the API key to use in your TypeScript/JavaScript application.
## Requirements [#requirements]
* Node.js 16+
* TypeScript 5.0+ (for TypeScript projects)
## License [#license]
Apache-2.0
---
# Files & documents (/chat/files)
Describe a document, presentation, image, or visualization and Sim creates it — streaming the content live into the resource panel as it writes. Attach any file to your message and Sim reads it, processes it, and saves it to your workspace.
## Uploading Files to the Workspace [#uploading-files-to-the-workspace]
Attach any file directly to your message in Chat — drag it into the input, paste it, or click the attachment icon. Sim reads the file as context and saves it to your workspace.
Use this to:
* Hand Sim a document and ask it to process, summarize, or extract data from it
* Upload a CSV and have it create a table from it
* Drop in a PDF and ask Sim to turn it into a knowledge base document
* Attach a design mockup and ask Sim to describe it or generate code from it
Uploaded files appear in the Files panel in the sidebar and are accessible to all workflows in the workspace. Sim can also fetch a file directly from a URL and save it for you: "Download the JSON at \[URL] and save it to the workspace."
## Creating Documents [#creating-documents]
Sim can write any text-based file — markdown, plain text, code files, CSV, JSON, or any other format:
* "Write a technical spec for the new auth system as a markdown file"
* "Create a CSV of our test accounts with columns for name, email, and plan tier"
* "Write a Python script that calls our workflow API and processes the response"
* "Draft a postmortem for the outage last Tuesday and save it as a markdown file"
* "Write a personalized outbound email for Acme Corp based on their recent funding announcement"
* "Draft a weekly ops digest summarizing workflow run counts, errors, and top failures for the past 7 days"
Files are saved to your workspace and accessible from the Files panel in the sidebar.
## Editing Existing Files [#editing-existing-files]
Open a file using `@filename` or the **+** menu, then describe the change:
* "Update the pricing section to reflect the new tiers"
* "Refactor this Python script to use async/await"
* "Add a section on error handling to this spec"
* "Rewrite the introduction of this report to be more concise"
## Presentations [#presentations]
Sim can generate `.pptx` files:
* "Create a pitch deck for Q3 review — 8 slides covering growth, retention, and roadmap"
* "Turn this research report into a 10-slide presentation"
* "Build a deck that walks through our API onboarding flow"
* "Build a battle card deck for our top 3 competitors — one slide each covering positioning, pricing, and how we win"
* "Create an account plan for Acme Corp — their priorities, our solution fit, and proposed next steps"
The file is saved to your workspace and can be downloaded.
## Images [#images]
Sim can generate images using AI, and can use an existing image as a reference to guide the output:
**Generating images:**
* "Generate a banner image for the new feature announcement — dark background, clean typography"
* "Create a diagram showing the data flow through our webhook pipeline"
* "Make a social card for the blog post with the title and author name"
**Using a reference image:**
* Attach an existing image to your message, then describe what you want: "Generate a new version of this banner with a blue color scheme instead of green"
* "Create a variation of this diagram with the boxes rearranged horizontally \[attach image]"
Generated images are saved as workspace files.
## Charts and Visualizations [#charts-and-visualizations]
Sim can generate charts and data visualizations from data you describe or reference:
* "Plot the workflow run counts from the metrics table as a bar chart grouped by week"
* "Create a line chart of token usage over the past 30 days from this data \[paste data]"
* "Generate a pie chart showing the distribution of lead sources from the leads table"
Visualizations are saved as files and rendered in the resource panel.
## Calculations & Data Processing [#calculations--data-processing]
For one-off calculations and data transformations, describe what you need and Sim runs it directly in the chat:
* "Parse this JSON and extract all records where status is 'failed'"
* "Calculate the p95 latency from these timing values: \[paste values]"
* "Convert these Unix timestamps to ISO 8601"
* "Deduplicate this list of emails, case-insensitive"
Results come back directly in the chat. Ask Sim to save the output as a file if you need it.
## File Viewer Modes [#file-viewer-modes]
When a file opens in the resource panel, you can switch between three views:
| Mode | What it shows |
| ----------- | -------------------------------- |
| **Editor** | Raw editable text |
| **Preview** | Rendered output (markdown, HTML) |
| **Split** | Editor and preview side by side |
---
# Chat (/chat)
Describe what you want and Sim handles it. Build a workflow, run research, generate a presentation, query a table, schedule a recurring job, send a Slack message — Sim knows your entire workspace and takes action directly.
## What You Can Do [#what-you-can-do]
| Area | What Sim can do |
| --------------------------------------------- | -------------------------------------------------------------------------- |
| **[Workflows](/chat/workflows)** | Build, edit, run, debug, deploy, and organize workflows |
| **[Research](/chat/research)** | Search the web, read pages, crawl sites, produce research reports |
| **[Files & Documents](/chat/files)** | Upload, create, edit, and generate documents, presentations, and images |
| **[Tables](/chat/tables)** | Create, query, update, and export workspace tables |
| **[Automation & Configuration](/chat/tasks)** | Schedule jobs, take immediate actions, connect integrations, manage tools |
| **[Knowledge Bases](/chat/knowledge)** | Create knowledge bases, add documents, and query content in plain language |
## How It Works [#how-it-works]
Sim receives a snapshot of your entire workspace with every message — all workflows, tables, knowledge bases, files, credentials, jobs, and integrations. This is why you can refer to things by name without specifying IDs or paths:
* "Run the invoice workflow"
* "Add a row to the leads table"
* "Deploy the summarizer as a chat"
No configuration, no context-setting. Just describe what you want:
* "Build a lead enrichment workflow that scores inbound signups and writes the results to the leads table"
* "Research our top 5 competitors and save a battle card for each one"
* "Schedule a daily job that checks for new high-fit prospects and posts them to #outbound in Slack"
* "Create a workflow that takes a contract PDF, extracts the key terms, and emails a summary to legal"
For complex tasks, Sim delegates to specialized subagents automatically. You'll see them appear as collapsible sections in the chat while they work — building, researching, writing files, executing actions.
{/* TODO: Screenshot of Chat showing a subagent section expanded mid-task — e.g., the Build or Research subagent actively working, with its collapsible header and steps visible in the thread. */}
## Adding Context [#adding-context]
Bring any workspace object into the conversation via the **+** menu, `@`-mentions, or drag-and-drop from the sidebar. Sim also opens resources automatically when it creates or modifies them.
{/* TODO: Screenshot of the resource panel with multiple tabs open — a workflow tab, a table tab, and a file tab — showing different resource types side by side. */}
| What to add | How it appears |
| ------------------ | ------------------------------------------------- |
| **Workflow** | Interactive canvas in the resource panel |
| **Table** | Full table editor in the resource panel |
| **File** | File viewer with editor, split, and preview modes |
| **Knowledge Base** | Knowledge base management UI |
| **Folder** | Folder contents |
| **Past task** | A previous Chat conversation |
## Layout [#layout]
Chat has two panes. On the left: the chat thread, where your messages and Sim's responses appear. On the right: the resource panel, where workflows, tables, files, and knowledge bases open as tabs. The panel is resizable; tabs are draggable and closeable.
---
# Knowledge bases (/chat/knowledge)
Create a knowledge base, add documents to it, and query it in plain language — all through conversation. Knowledge bases you create in Chat are immediately available to Agent blocks in any workflow.
## Creating Knowledge Bases [#creating-knowledge-bases]
Describe the knowledge base and Sim creates it:
* "Create a knowledge base called 'Product Docs'"
* "Set up a knowledge base for our support team — call it 'Support KB'"
* "Create a competitive intelligence knowledge base"
* "Create a knowledge base from our sales playbook and attach it to the outbound agent workflow"
* "Set up a customer success knowledge base — I'll add our onboarding guides and past case studies to it"
## Adding Documents [#adding-documents]
Add documents by attaching files to your message, pasting text, or pointing Sim at a URL:
* "Add this PDF to the Product Docs knowledge base \[attach file]"
* "Add the following text to the Support KB as a new document: \[paste content]"
* "Fetch the page at \[URL] and add it to the competitive intelligence knowledge base"
* "Add these three uploaded case studies to the customer success knowledge base"
Sim processes and indexes each document automatically. Once indexed, the content is searchable by any Agent block that has the knowledge base attached.
{/* TODO: Screenshot of Sim confirming a document was added and indexed — showing the document name and its indexed status in the knowledge base. */}
## Querying Knowledge Bases [#querying-knowledge-bases]
Ask Sim a question and it searches the specified knowledge base to answer:
* "What does the Product Docs knowledge base say about our refund policy?"
* "Search the Support KB for anything related to SSO setup errors"
* "What are the key differences between our Pro and Enterprise plans, based on the product docs?"
* "Find everything in the competitive intelligence knowledge base about \[competitor]'s pricing"
## Connectors [#connectors]
For knowledge bases that should stay current automatically, connectors sync content from external services on a schedule — no manual uploads needed. New content is added, changed content is re-processed, and deleted content is removed on every run.
Connectors are configured through the knowledge base settings, not through Chat. Once connected, all synced content is immediately searchable by Sim and by any Agent block with the knowledge base attached.
Sim ships with 49 built-in connectors, including Notion, Google Drive, Slack, GitHub, Confluence, HubSpot, Salesforce, Gmail, and more.
Examples of what you can sync:
* **Notion** — sync a workspace, a database, or a specific page tree
* **Google Drive / Dropbox / OneDrive** — sync documents from cloud storage
* **GitHub** — sync a repository's markdown and code files
* **Slack** — sync channel history
* **Confluence / Jira** — sync your internal wiki or issue tracker
* **HubSpot / Salesforce** — sync CRM records into a searchable knowledge base
See [Connectors](/knowledgebase/connectors) for setup steps, sync frequency options, and managing connector status.
## Managing Knowledge Bases [#managing-knowledge-bases]
List, inspect, and clean up knowledge bases in plain language:
* "What knowledge bases are in this workspace?"
* "How many documents are in the Support KB?"
* "Remove the outdated pricing doc from the Product Docs knowledge base"
* "Delete the old-competitive-intel knowledge base"
## Using Knowledge Bases in Workflows [#using-knowledge-bases-in-workflows]
Knowledge bases created in Chat are immediately available to Agent blocks in any workflow. Attach a knowledge base to an Agent block and it will use semantic search to retrieve relevant content at runtime.
See [Knowledge Base](/knowledgebase) for full details on document processing settings, search configuration, and connector syncing.
---
# Sim Mailer (/chat/mailer)
Sim Mailer gives your workspace a dedicated email address. Forward or send emails to it and Sim will process them as tasks — reading the subject, body, and any attachments, then replying to the thread with the result.
## Getting Started [#getting-started]
1. Navigate to **Settings** → **Inbox**
2. Toggle the inbox on
3. Optionally choose a custom address prefix (e.g., `acme` → `acme@mothership.sim.ai`)
4. Copy your inbox address and start sending emails
If you skip the custom prefix, one is generated automatically.
Changing your address creates a new inbox. The old address stops working immediately.
## What You Can Send [#what-you-can-send]
Write your email like you would to a colleague. The subject and body become the task prompt.
**Attachments are fully supported.** Images, PDFs, and documents (up to 10 MB each) are read by Sim and displayed inline in the conversation; images show as previews.
| Good email | Why it works |
| -------------------------------------------------- | --------------------------------- |
| "Summarize the attached PDF and list action items" | Clear task with an attachment |
| "What's in this image?" with a photo attached | Sim reads and describes the image |
| "Draft a reply to this forwarded thread" | Uses the email body as context |
## Allowed Senders [#allowed-senders]
Only authorized senders can create tasks. Emails from anyone else are automatically rejected.
* **Workspace members** are allowed by default — no setup needed
* **External senders** can be added manually with an optional label for easy identification
External senders are email addresses that can create inbox tasks. They are not the same as external workspace members, who have workspace access in Sim without joining your organization.
Manage your allowed senders list in **Settings** → **Inbox** → **Allowed Senders**.
## Tracking Tasks [#tracking-tasks]
Every email becomes a task you can track in **Settings** → **Inbox**:
* **Search** by subject, sender, or body content
* **Filter** by status to find what you need
* **Click** any completed or failed task to jump to the full conversation
### Task Statuses [#task-statuses]
| Status | Meaning |
| -------------- | ---------------------------------------------------------------------------- |
| **Received** | Email accepted, queued for processing |
| **Processing** | Sim is actively working on it |
| **Completed** | Done — the result was sent as an email reply |
| **Failed** | Something went wrong during execution |
| **Rejected** | Email blocked (sender not allowed, automated sender, or rate limit exceeded) |
## Conversations [#conversations]
Each email task creates a conversation in your workspace. You can continue the conversation in Chat, and any follow-up emails in the same thread are linked to the same conversation.
---
# Research (/chat/research)
Ask Sim to research anything and it figures out the best approach — searching the web, reading specific pages, crawling sites, looking up technical docs. Just describe what you want to know.
## Asking Questions [#asking-questions]
Ask anything — about a company, a competitor, a market, a technical question, or a specific URL:
* "What did Salesforce, HubSpot, and Gong each ship in the past 30 days? Summarize the key product updates."
* "What's Acme Corp's tech stack, recent hires, and open engineering roles?"
* "Find everything published about \[competitor] in the past 90 days — press, product changes, job postings."
* "What are the current rate limits on the Anthropic API?"
* "Read \[URL] and tell me what changed in this release"
* "What does Stripe's API say about handling webhooks with idempotency keys?"
* "Who are the main players in AI-powered revenue operations, and how do they differentiate?"
Sim returns an answer directly in the chat. For anything that needs a longer written output, ask it to save the result as a file.
## Research Reports [#research-reports]
When you need a structured, saved document rather than a chat answer, ask Sim to write it up. Sim searches, reads, and cross-references multiple sources until it has enough to produce a full report. The output is saved as a file in your workspace and opened in the resource panel.
{/* TODO: Screenshot of a completed research report open in the resource panel as a file — showing a structured markdown document with sections, findings, and citations. */}
* "Research the top 10 AI SDR tools — pricing, features, positioning, and what customers say. Save as a competitive analysis."
* "Do a full market landscape for AI in healthcare diagnostics — major players, funding, use cases, and regulatory environment."
* "Research how our top 5 competitors handle multi-tenant auth — pricing, architecture, and any known vulnerabilities. Write it up as a report."
* "Find every public case study on AI agents in financial compliance from the past 2 years. Summarize the key outcomes and save as a markdown file."
* "Build a battle card for \[competitor] — their positioning, pricing, strengths, weaknesses, and how we win against them."
---
# Tables (/chat/tables)
Create a table from a description or a CSV, query it in plain language, add or update rows, and export the results — all through conversation. Tables open in the resource panel as soon as they're created or referenced.
## Creating Tables [#creating-tables]
Describe the schema and Sim creates the table:
* "Create a leads table with columns for name, email, company, status, and created date"
* "Create a table that matches the structure of this CSV \[attach file]"
* "Set up an errors table with: id (text), message (text), workflow (text), timestamp (date), resolved (boolean)"
* "Create a prospect table for outbound — company, domain, employee count, industry, ICP score, and last contacted date"
* "Set up an enrichment results table to store output from the lead enrichment workflow: email, company, title, LinkedIn URL, fit score"
## Querying Data [#querying-data]
Ask questions about table contents in plain language:
* "How many rows in the leads table have status 'qualified'?"
* "Show me all records from the past 7 days where score is above 0.8"
* "What are the top 5 most common error messages in the failures table?"
* "Are there any duplicate emails in the contacts table?"
* "How many prospects have an ICP score above 0.75 and haven't been contacted in the past 30 days?"
* "What's the conversion rate from 'contacted' to 'meeting booked' in the pipeline table this month?"
Sim translates the question into a structured query and returns the results.
## Adding and Updating Rows [#adding-and-updating-rows]
Add individual rows, bulk-update based on a condition, or delete records — all in plain language:
* "Add a row to the leads table: Acme Corp, [jane@acme.com](mailto:jane@acme.com), status pending"
* "Mark all rows in the queue table as processed where created\_at is before today"
* "Update the price column for all rows where tier is 'pro' to 49"
* "Delete all rows in the test\_events table"
## Exporting [#exporting]
Export a full table or a filtered subset as a CSV. The file is saved to your workspace and can be downloaded or referenced in other workflows:
* "Export the leads table to a CSV"
* "Export all rows where status is 'closed' and save as a file"
## Using Tables in Workflows [#using-tables-in-workflows]
Tables created in Chat are immediately available in workflows via the [Table tool](/integrations/table). Reference a table by name — no additional configuration needed.
---
# Automation & configuration (/chat/tasks)
Sim can act on your behalf right now — send a message, create an issue, call an API — or on a schedule, running a prompt automatically every hour, day, or week. It can also connect integrations, set environment variables, add MCP servers, and create custom tools.
## Scheduled Jobs [#scheduled-jobs]
A scheduled job is a saved Chat prompt that runs on a cron schedule. On each run, Sim reads the current workspace state and executes the job's prompt as if you had just sent it.
### Creating a Job [#creating-a-job]
Describe the recurring task and how often it should run:
* "Every morning at 8am, check the leads table for new entries and post a summary to #sales in Slack"
* "Every Monday at 9am, pull last week's workflow run counts and write a report to the workspace"
* "Run the data sync workflow every 6 hours"
* "On the first of every month, export the billing table to CSV and email it to [finance@example.com](mailto:finance@example.com)"
* "Every weekday at 7am, check for new funding announcements from companies in our ICP and post the top 5 to #market-intel in Slack"
* "Every Sunday night, run the lead enrichment workflow on all prospects added in the past week and update their scores in the table"
* "Daily at 6am, pull the previous day's workflow errors, summarize the top issues, and post to #eng-alerts"
Sim sets the cron expression and stores the job prompt. The first run happens at the next scheduled time.
### Viewing Job Logs [#viewing-job-logs]
* "Show me the last 5 runs of the weekly report job"
* "Did the sync job run successfully this morning?"
* "What did the Monday digest job do last week?"
Logs show run time, status (completed, failed), and a summary of what the agent did.
### Managing Jobs [#managing-jobs]
* "Pause the morning summary job"
* "Change the sync job to run every 3 hours instead of 6"
* "Delete the onboarding digest job"
* "What scheduled jobs are currently active?"
## Taking Direct Action [#taking-direct-action]
For requests that should happen right now — without building a workflow — just ask. Sim acts immediately using the credentials connected to your workspace.
{/* TODO: Screenshot of Chat showing the "Taking action" subagent label active during a direct action — e.g., posting to Slack or sending an email. Shows the subagent inline in the chat thread. */}
| Request | What happens |
| -------------------------------------------------------------------------- | ------------------------------------ |
| "Send a Slack message to #eng that the deploy finished" | Posts to Slack immediately |
| "Email the Q3 report to [jane@example.com](mailto:jane@example.com)" | Sends via connected Gmail or Outlook |
| "Create a GitHub issue: auth tokens not rotating on logout" | Opens an issue in the specified repo |
| "Add a contact to HubSpot: Acme Corp, [ceo@acme.com](mailto:ceo@acme.com)" | Creates the contact via HubSpot API |
| "Call the webhook at \[URL] with this JSON payload" | Makes the HTTP request |
If an integration isn't connected, Sim walks you through connecting it.
## Connecting Integrations [#connecting-integrations]
Sim can connect new OAuth integrations and API credentials on demand:
* "Connect my Google account"
* "Add the Slack workspace for our team"
* "Set up GitHub with my personal access token"
{/* TODO: Screenshot of Sim walking through connecting an integration — e.g., the Integration subagent active with an OAuth prompt or confirmation that a credential was connected. */}
Once connected, credentials are available to Sim for direct actions and scheduled jobs, and to all workflows in the workspace.
Connected credentials are shared across the workspace. Any workflow that uses the same integration will automatically use the same credential.
See [Credentials](/platform/credentials) for managing connected accounts.
## Environment Variables [#environment-variables]
Environment variables are workspace-scoped values — API keys, connection strings, and configuration that workflows reference via `{{ENV_VAR}}` syntax rather than hardcoding. Set them once and every workflow in the workspace can use them.
* "Set the DATABASE\_URL environment variable to 'postgres\://...'"
* "Add an OPENAI\_API\_KEY environment variable"
* "Add a WEBHOOK\_SECRET variable for the inbound webhook workflow"
* "Update the SCORING\_API\_URL variable to point to the new endpoint"
* "What environment variables are currently set?"
{/* TODO: Screenshot of Sim confirming an environment variable was set — e.g., a response message showing the variable name was saved. */}
## MCP Servers [#mcp-servers]
MCP (Model Context Protocol) servers expose tools from external services that Agent blocks can call inside workflows. Connecting an MCP server makes all of its tools available in the workflow editor's tool picker — no custom integration code required.
Sim can add and manage MCP servers connected to your workspace:
* "Add the Stripe MCP server using my API key"
* "Remove the old analytics MCP server"
* "What MCP servers are connected to this workspace?"
* "Update the endpoint for the internal tools MCP server to \[URL]"
Once added, MCP tools appear in the workflow editor's tool picker and can be called from any Agent block.
{/* TODO: Screenshot of Sim confirming an MCP server was added or updated — showing the server name and its status. */}
## Custom Tools [#custom-tools]
Custom tools are single HTTP endpoints you define manually — useful for internal APIs and services that don't have a built-in Sim integration or an MCP server. Once created, they appear in the workflow editor alongside built-in tools and can be called from any Agent block.
Sim can build custom tools from a description:
* "Create a custom tool that calls our internal scoring API at \[URL] with a POST request and returns the score field"
* "Build a tool for our Zendesk instance that creates a ticket with a subject and body"
* "Create a tool that hits our internal enrichment API with a domain and returns company size, industry, and funding stage"
* "Add a tool that calls our CRM's REST API to look up a contact by email and return their account owner"
Custom tools appear in the workflow editor and are callable from any Agent block alongside built-in tools.
{/* TODO: Screenshot of Chat with the Custom Tool subagent active — showing it building a tool definition. */}
---
# Workflows (/chat/workflows)
Describe a workflow and Sim builds it. Reference an existing one by name and Sim edits it. No canvas navigation required — every change appears in the resource panel in real time.
## Creating Workflows [#creating-workflows]
Describe what the workflow should do — what triggers it, what it should do, which integrations it needs, and what it should return. Sim builds it and opens the canvas in the resource panel.
* "Build a workflow that takes a URL, scrapes the page, summarizes it with Claude, and sends the summary to a Slack channel"
* "Create a workflow triggered by a webhook that extracts invoice data from a PDF and writes it to the billing table"
* "Build an outbound workflow: take a company name and domain, enrich it with firmographic data, score the fit, and draft a personalized cold email"
* "Create a lead enrichment workflow that takes an email from a form submission, looks up the company, and writes the enriched record to the leads table"
* "Build a customer onboarding workflow: when a new user signs up, send a welcome email, create a HubSpot contact, and post a notification to #new-customers in Slack"
## Editing Workflows [#editing-workflows]
{/* TODO: Screenshot of Chat with the Edit subagent active and a change applied to an open workflow — e.g., a new block added or a configuration updated, visible on the canvas in the resource panel. */}
Open an existing workflow with `@workflow-name` or the **+** menu, then describe the change. Sim reads the current structure before modifying it — you don't need to explain what already exists.
* "Add a condition that routes to a different branch if the confidence score is below 0.7"
* "Replace the GPT-4o model with Claude Opus 4.6 on the summarizer block"
* "Add a Slack notification at the end that includes the output"
## Running Workflows [#running-workflows]
Ask Sim to run a workflow and it handles the execution:
* "Run the data sync workflow"
* "Run the invoice processor with this PDF \[attach file]"
* "Test the lead scoring workflow with these inputs: name=Acme, score=0.4"
Execution streams back to the chat. The workflow in the resource panel shows live block-by-block state.
## Reading Logs [#reading-logs]
Sim can retrieve and interpret execution logs for any workflow in the workspace:
* "Show me the last 10 runs of the pipeline workflow"
* "Why did the invoice workflow fail yesterday?"
* "What did the extractor block return in the most recent run?"
Logs include per-block execution state, outputs, errors, and timing.
## Debugging [#debugging]
When a workflow fails, tell Sim to debug it:
* "Debug the last failed run of the content pipeline"
* "The summarizer block is returning empty output — figure out why"
Sim reads the failure logs, identifies the cause, applies a fix, and can re-run to confirm.
{/* TODO: Screenshot of the Debug subagent section in Chat showing it reading logs and applying a fix. */}
## Deploying [#deploying]
Sim can deploy a workflow as any of the three deployment types:
| Deployment type | What it creates |
| --------------- | -------------------------------------------------------------- |
| **API** | A REST endpoint at `https://sim.ai/api/workflows/{id}/execute` |
| **Chat** | A hosted conversational interface with a shareable URL |
| **MCP tool** | An MCP server that exposes the workflow as a tool |
Ask: "Deploy the invoice workflow as an API and generate an API key."
Sim can also roll back: "Revert the billing workflow to the version from last Tuesday."
See [API Deployment](/workflows/deployment/api) and [Chat Deployment](/workflows/deployment/chat) for full details on each deployment type.
## Organizing Workflows [#organizing-workflows]
Sim can create and manage folders to keep your workspace organized.
**Folders:**
* "Create a folder called 'Data Pipelines'"
* "Move the invoice workflow into the billing folder"
* "Move the billing folder inside the finance folder"
* "Delete the old-experiments folder"
**Renaming and moving:**
* "Rename the 'test\_v2' workflow to 'lead-scorer'"
* "Move the summarizer workflow to the research folder"
{/* TODO: Screenshot showing Sim confirming a folder or workflow organization action — e.g., a message confirming "Moved 'invoice-processor' into 'billing' folder" with the resource panel showing the folder open. */}
## Workflow Variables [#workflow-variables]
Sim can set global variables on a workflow — values accessible across all blocks in that workflow at runtime:
* "Set the API\_ENDPOINT variable on the sync workflow to '[https://api.example.com/v2](https://api.example.com/v2)'"
* "Update the MAX\_RETRIES variable on the pipeline workflow to 5"
Variables set this way are available via `` syntax inside any block in the workflow.
## Deleting Workflows [#deleting-workflows]
* "Delete the old\_api\_prototype workflow"
* "Delete all workflows in the deprecated folder"
---
# Editor (/files/editor)
Every markdown file in your workspace opens in a **rich editor**. Type markdown and it renders as you go, or format visually with the toolbar and slash menu. What you see is exactly what gets saved — plain markdown underneath, no lock-in.
## Formatting text [#formatting-text]
Select any text to bring up the formatting toolbar — bold, italic, strikethrough, inline code, and links. The same marks appear instantly as you type the markdown for them, like `**bold**` or `*italic*`. Links show a hover card so you can open, copy, edit, or remove them without hunting through the source.
## Structure [#structure]
Headings, blockquotes, and dividers keep long documents scannable. Type `# ` through `###### ` for headings, `> ` for a quote, and `---` for a divider.
## Lists and checklists [#lists-and-checklists]
Bullet, ordered, and nested lists all work, plus task lists you can tick right in the document.
## Tables [#tables]
Insert a table from the slash menu, then click any cell for the floating table toolbar — add or remove rows and columns, toggle the header row, or delete the table. Drag a column border to resize it.
## Code blocks [#code-blocks]
Fenced code blocks are syntax-highlighted, with a language picker in the corner. Pick `mermaid` to render a live diagram instead of code.
## Images [#images]
Paste or drag an image straight into the document, then drag a corner to resize it.
## Slash menu and shortcuts [#slash-menu-and-shortcuts]
Type `/` anywhere to insert any block — heading, list, table, code block, image, and more — without leaving the keyboard. Familiar shortcuts work too: **Cmd/Ctrl + B** for bold, **Cmd/Ctrl + I** for italic, and **Cmd/Ctrl + K** to add a link over selected text.
## Markdown fidelity [#markdown-fidelity]
The editor round-trips your markdown exactly — it saves what you wrote, with no reformatting churn.
A few constructs can't be represented visually without losing information on save — footnotes, raw HTML, and HTML comments. When a file contains one of these, it opens **read-only** so the original source is preserved untouched. Everything is still rendered faithfully; you just can't edit that file inline.
---
# Generating files (/files/generating)
A generated file is an artifact a workflow run creates: a report, a CSV, a rendered audio clip. It starts as a value a block produces and becomes a workspace file when a [File](/integrations/file) block writes it to the [Files](/files) store. Once saved, it has a name, a size, and a URL, and any later run can read it back.
Like a build pipeline that produces artifacts and stores them in an artifact repository, a workflow produces file artifacts that land in your workspace Files store, indexed by ID and shared across every workflow.
{/* VISUAL: flow diagram: [Agent/Function block produces content] → [File block, Write] → [Files panel, file visible] */}
## What produces file content [#what-produces-file-content]
Most generated files start as the output of an earlier block. Two patterns are common.
A block returns **text content** you want to keep. An [Agent](/workflows/blocks/agent) writes an analysis or summary; a [Function](/workflows/blocks/function) builds a CSV or formats a report. That text is part of the block's output, read by reference as `` or ``. To make it a file, you pass that value into a File block set to Write.
A block returns a **file object** directly. ElevenLabs text-to-speech returns an `audioFile`; an image generator returns a generated image; the File block's own Read operation returns parsed files. These are already [UserFile](/files/passing-files) objects (an object with `id`, `name`, `url`, `size`, and `type`), so they appear in the output panel as files with no Write step. You can hand one to a downstream block, or write its content to the Files store to persist it.
A block's output is remembered under the block's name for the rest of the run, and a later block reads it by key, like `` or ``. Producing content and saving it are two separate steps: the producing block holds the value, the File block persists it.
## Saving content with the File block [#saving-content-with-the-file-block]
The [File](/integrations/file) block's **Write** operation creates a new workspace file. It takes two required fields: a `fileName` (like `report.md`) and the `content` string to store. It returns the saved file's details.
{/* VISUAL: File Write anatomy: inputs (fileName, content, contentType?) → outputs (id, name, size, url) */}
To save an Agent's analysis, connect Agent into a File block, set the operation to Write, and reference the Agent's output: `fileName` = `research_summary.md`, `content` = ``. When the workflow runs, the File block writes the file and produces:
* `id`: the canonical file ID, used to fetch the file later.
* `name`: the final file name after any deduplication (see below).
* `size`: the byte count.
* `url`: an absolute URL to download or preview the file.
The content type is detected from the file extension: `.csv` becomes `text/csv`, `.pdf` becomes `application/pdf`, `.md` becomes `text/markdown`. To set it yourself, fill in `contentType` in advanced mode.
If a file with the same name already exists in the workspace, Write does not overwrite it. It appends a numeric suffix instead: a second `data.csv` is saved as `data (1).csv`, a third as `data (2).csv`. To add to an existing file rather than create a new one, use the **Append** operation, which writes content to the end of a named file.
## Where the file goes [#where-the-file-goes]
A saved file lands in the workspace [Files](/files) store, the same place uploads live. It shows up in the Files panel in the sidebar with its name, size, type icon, and modified date, grouped by category: document, image, audio, video, or code. From there you can preview it, rename it, move it into a folder, or download it by URL.
{/* VISUAL: Files panel UI: generated files listed with name, size, type icon, owner, modified date, folder */}
Files are scoped to the workspace, not to one workflow. A file written by one workflow is visible to every other workflow in the same workspace. Any later run can read it back with the File block's Read or Get operation, or by selecting it in a file picker.
During a run, the file also appears in the output panel as the File block's output, shown as a structured object with its `id`, `name`, `url`, and `size`. The output panel shows you one run as it happens, while the Files store is where the file stays afterward.
{/* VISUAL: output panel tree: file object (id, name, url, size, type) during a run, beside the same file in the Files store */}
## Returning a generated file from a deployment [#returning-a-generated-file-from-a-deployment]
When a workflow is deployed as an [API](/workflows/deployment/api), a generated file can be part of the response. Reference the file in a [Response](/workflows/blocks/response) block, or include its ID in the object you return. The caller uses the `url` or `id` to fetch the file from the workspace store. The file itself stays in the Files store, and the response carries a pointer to it, not the bytes.
## Next [#next]
---
# Overview (/files)
A **file** is a document, image, spreadsheet, or PDF in your workspace. Files are how documents and media move into and out of your agents. Your team uploads them, you create them in the editor, or a workflow produces them, and they all live in one store shared across the workspace.
Any [workflow](/workflows) can read a file or produce one. You might upload a contract for an agent to review, generate a report from a table, or hand a workflow the document it needs to answer a question.
## How files fit the workspace [#how-files-fit-the-workspace]
* **[Workflows](/workflows)** read files, like a PDF to summarize, and produce them, like a rendered report. See [using files in workflows](/files/using-in-workflows).
* **[Knowledge bases](/knowledgebase)** are built from files you upload, turning their contents into searchable memory.
* **[Deployments](/workflows/deployment)** can take a file as input and return one as output.
Use a file when the document or media itself is what matters. Use a [table](/tables) when you need structured rows and fields, and a [knowledge base](/knowledgebase) when an agent needs to search across many documents.
---
# Passing files (/files/passing-files)
A file moves through a workflow as a standardized **file object**. Blocks receive it, act on it, and pass it on — this page covers the object's shape, how to reference it between blocks, and how files enter and leave through the API.
## File Objects [#file-objects]
When blocks output files (like Gmail attachments, generated images, or parsed documents), they return a standardized file object:
```json
{
"id": "f_8c2...",
"name": "report.pdf",
"url": "https://...",
"size": 245678,
"type": "application/pdf",
"base64": "JVBERi0xLjQK..."
}
```
You can access any of these properties when referencing files from previous blocks.
## The File Block [#the-file-block]
The **File block** brings a file into a workflow. It accepts files from any source and outputs standardized file objects every block understands.
**Inputs:**
* **Uploaded files** - Drag and drop or select files directly
* **External URLs** - Any publicly accessible file URL
* **Files from other blocks** - Pass files from Gmail attachments, Slack downloads, etc.
**Outputs:**
* A list of `UserFile` objects with consistent structure (`id`, `name`, `url`, `size`, `type`, `base64`)
* `contents` - Extracted text per file (the Get Content operation)
* `combinedContent` - All fetched files' text merged into one string (the Fetch operation)
**Example usage:**
```
// Get all files from the File block
// Get the first file
// Get the first file's extracted text (Get Content operation)
```
The File block automatically:
* Detects file types from URLs and extensions
* Extracts text from PDFs, CSVs, and documents
* Generates base64 encoding for binary files
* Creates presigned URLs for secure access
Use the File block when you need to normalize files from different sources before passing them to other blocks like Vision, STT, or email integrations.
## Passing Files Between Blocks [#passing-files-between-blocks]
Reference files from previous blocks using the tag dropdown. Click in any file input field and type `<` to see available outputs.
**Common patterns:**
```
// Single file from a block
// Pass the whole file object
// Access specific properties
```
Most blocks accept the full file object and extract what they need automatically. You don't need to manually extract `base64` or `url` in most cases.
## Triggering Workflows with Files [#triggering-workflows-with-files]
When calling a workflow via API that expects file input, include files in your request:
```bash
curl -X POST "https://sim.ai/api/workflows/YOUR_WORKFLOW_ID/execute" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"document": {
"name": "report.pdf",
"base64": "JVBERi0xLjQK...",
"type": "application/pdf"
}
}'
```
```bash
curl -X POST "https://sim.ai/api/workflows/YOUR_WORKFLOW_ID/execute" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"document": {
"name": "report.pdf",
"url": "https://example.com/report.pdf",
"type": "application/pdf"
}
}'
```
The workflow's Start block should have an input field configured to receive the file parameter.
## Receiving Files in API Responses [#receiving-files-in-api-responses]
When a workflow outputs files, they're included in the response:
```json
{
"success": true,
"output": {
"generatedFile": {
"name": "output.png",
"url": "https://...",
"base64": "iVBORw0KGgo...",
"type": "image/png",
"size": 34567
}
}
}
```
Use `url` for direct downloads or `base64` for inline processing.
## Blocks That Work with Files [#blocks-that-work-with-files]
**File inputs:**
* **File** - Parse documents, images, and text files
* **Agent** - Read images with a vision-capable model, or documents as text
* **Mistral Parser** - Extract text from PDFs
**File outputs:**
* **Gmail** - Email attachments
* **Slack** - Downloaded files
* **TTS** - Generated audio files
* **Video Generator** - Generated videos
* **Image Generator** - Generated images
**File storage:**
* **Supabase** - Upload/download from storage
* **S3** - AWS S3 operations
* **Google Drive** - Drive file operations
* **Dropbox** - Dropbox file operations
Files are automatically available to downstream blocks. The engine handles all file transfer and format conversion.
## Best Practices [#best-practices]
1. **Use file objects directly** - Pass the full file object rather than extracting individual properties. Blocks handle the conversion automatically.
2. **Check file types** - Ensure the file type matches what the receiving block expects. An Agent using a vision-capable model can read images, while the File block handles documents.
3. **Consider file size** - Large files increase run time. For very large files, consider using storage blocks (S3, Supabase) for intermediate storage.
---
# Using files in workflows (/files/using-in-workflows)
A file is a document, image, spreadsheet, or PDF in your workspace. A workflow can read a file to act on its contents, pass a file to a block or tool that needs one (attach a PDF to an email, send an image to a vision model), or produce a new file and save it. The [File](/integrations/file) block is how a file enters or leaves a workflow; the work in between is done by whatever block the task calls for.
What you do with a file depends on the task, so this page covers the File block's operations and how a file moves between blocks rather than one fixed recipe. The example we'll use throughout reads `report.pdf`, asks an agent to summarize it, and saves the summary as `summary.md`, which exercises reading, processing, and writing in one workflow.
## The File block [#the-file-block]
The **File** block is one block with five operations, chosen from a dropdown. Each operation is a different way a file, or its contents, enters or leaves the workflow.
| Operation | What it does | Outputs |
| --------------- | -------------------------------------------------------------- | --------------------------- |
| **Read** | Take an existing workspace file, by file picker or by file ID. | `files` |
| **Get Content** | Extract a workspace file's text, by file picker or by file ID. | `contents` |
| **Fetch** | Download and parse a file from an external URL. | `files`, `combinedContent` |
| **Write** | Create a new workspace file from a name and text content. | `id`, `name`, `size`, `url` |
| **Append** | Add text to the end of an existing workspace file. | `id`, `name`, `size`, `url` |
Read hands the next block the **file itself**; Get Content hands it the **text inside**. Fetch brings in both for an external URL. Write and Append put a file out. A workflow uses only the operations its task needs, often just Read. The two sections below cover Read and Write; the other operations are variants noted alongside.
{/* VISUAL: File block config UI. Operation dropdown open showing Read / Get Content / Fetch / Write / Append */}
## Reading a file in [#reading-a-file-in]
In our example, the first File block is set to **Read**, with `report.pdf` chosen from the file picker. When it runs, it produces `files`: a list of **file objects**, one per file read. The first is ``.
When the next step needs the file's *text* rather than the file itself, use **Get Content** instead: it extracts the text and outputs `contents`, an array with one string per file, read as ``.
A **file object** is the standard shape Sim uses for every file. It carries the file's details:
```jsonc
{
"id": "wf_V1StGXR8z5jdHi6B…", // workspace file ID
"name": "report.pdf",
"url": "https://…", // where to access it
"size": 248120, // bytes
"type": "application/pdf"
}
```
You rarely type a reference by hand. Wherever a block parameter accepts a file or a value, the builder lists the available outputs and you pick the one you want. Read mode also takes a file ID directly in advanced mode, which is how you read a file produced earlier in the same run.
**Fetch** brings in files that live outside the workspace. Point it at a URL, and add request headers (such as `Authorization: Bearer …`) when the download needs authentication. It outputs `files` like Read does, plus `combinedContent`: the fetched files' text merged into one string.
{/* VISUAL: File block in Read mode, file picker open with report.pdf selected; callout on the files[] output */}
## Processing the file [#processing-the-file]
Once a file is read, a processing block reads that output by name. Two blocks do this, and they consume the file differently.
### Agent block [#agent-block]
An [Agent](/workflows/blocks/agent) block has a **Files** input. Reference the read file there, ``, and write the instruction in the prompt: "Summarize this document." The agent receives the file object, not just its text, so a **vision-capable model** can analyze images and scanned pages directly. Other models work from the file's text content.
In our example the Agent reads ``, summarizes it, and keeps the summary under its own name as ``.
{/* VISUAL: Agent block config. Files input bound to , prompt "Summarize this document" */}
### Function block [#function-block]
A [Function](/workflows/blocks/function) block runs code, and it usually works with file **text**. Read the file with **Get Content** and pass the extracted text, ``, and the code can parse, filter, or reshape it and return the result as its own output. A Function can also take the file object itself and read it in code with the `sim.files` helpers, like `await sim.files.readText(file)` — see [the Function block](/workflows/blocks/function) for those. Use a Function when the file is structured text (a CSV or JSON dump) and you want exact, deterministic processing instead of a model's interpretation.
The two blocks differ in what they take. An **Agent** takes the file object on its Files input, while a **Function** typically takes the file's text from Get Content's `contents`. Both store their result under their own name for the next block to read.
## Writing a file out [#writing-a-file-out]
Writing a file is optional, and many workflows skip it. The agent's summary could be returned in the response, posted to Slack, or emailed as-is without ever becoming a workspace file. Write a file when you specifically need a new one to keep, download, or hand to a later run.
The last block in our example is a File block set to **Write**. Give it a file name and the content to save:
* `fileName`: `summary.md`
* `content`: ``
Write creates a new workspace file and returns its `id`, `name`, `size`, and `url`. If a file with that name already exists, Write keeps both by adding a numeric suffix to the new one. The saved file lands in your workspace [files](/files), ready for the next run, a download, or another workflow.
{/* VISUAL: run log showing the File Write step with the returned file id, name, and url */}
**Append** adds to a file instead of replacing it. Target an existing workspace file by name and give it the content to add to the end. Use it to accumulate across runs, such as appending each run's observation to one `notes.md`.
## Composing the steps [#composing-the-steps]
Each block references the previous one by name, so you compose only the steps a task needs. A contract read by an Agent that returns a verdict stops at processing, and an uploaded image described by a vision model never touches Write, while a fetched CSV cleaned by a Function and saved as a new file uses all three. Reading a file in is common, and writing one out is only for when the result is itself a file.
For the file-object schema in full, base64 access, and how files move across API and chat triggers, see [Passing files](/files/passing-files).
## Next [#next]
---
# Audit Logs (/cli/audit-logs)
`sim audit-logs` is also spelled `sim audit-log`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Get audit log [#get-audit-log]
```bash
sim audit-logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Audit-log entry identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------- |
| `--organization ` | Yes | Organization ID (personal API key required). |
## List audit logs [#list-audit-logs]
```bash
sim audit-logs list [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--action ` | No | Filter by exact action name. |
| `--resource-type ` | No | Filter by resource type. Accepts a comma-separated set; members are trimmed and deduplicated, and member order affects neither the result nor the cursor. |
| `--resource-id ` | No | Filter by exact resource identifier. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--include-departed` | No | Include actions by users who have left the organization. |
| `--no-include-departed` | No | Send --include-departed as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--organization ` | Yes | Organization ID (personal API key required). |
| `--actor-email ` | No | Filter by actor email address. |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
---
# Authentication (/cli/authentication)
The CLI authenticates with a Sim API key. `sim login` mints and stores one; in CI
you supply one through the environment instead.
## Signing in [#signing-in]
```bash
sim login
```
The terminal prints a pairing code and a URL:
```
Pairing code: K7M2-P9XT
Confirm this code matches what the browser shows before approving.
https://sim.ai/cli/auth?request=…&scope=platform
Waiting for approval…
✓ Logged in. Key stored in /Users/you/.sim/credentials
Personal key, defaulting to ws_abc123. Override per command with --workspace.
```
There is no loopback listener, so this works over SSH and inside containers.
Confirm the pairing code in the browser matches the one in your terminal before
approving. That check is what binds the approval to your terminal.
| Option | What it does |
| ----------------- | --------------------------------------------------------- |
| `--no-browser` | Print the URL instead of opening a browser |
| `--scope ` | Key space to mint from: `platform` (default) or `copilot` |
| `-y, --yes` | Overwrite an existing profile without prompting |
### Picking a workspace [#picking-a-workspace]
You choose the workspace on the approval page. `sim login` issues a **personal** key. The workspace you pick becomes the
profile's default `workspace`; it does **not** restrict the key to that
workspace. Target another workspace the key can reach with `--workspace`:
```bash
sim workflows list --workspace ws_other
```
`sim login --workspace ` preselects a workspace in the picker, and
re-logging into an existing profile preselects the one already configured.
## Checking who you are [#checking-who-you-are]
```bash
sim whoami
```
Prints the resolved endpoint, workspace, output format, and account, and which
source each value came from.
## Signing out [#signing-out]
```bash
sim logout # remove the stored key
sim logout --all # remove the profile entirely, including its settings
```
`sim logout` removes the key from disk but does **not** revoke it. Revoke keys in
Sim under **Settings → API keys**.
## Authenticating CI [#authenticating-ci]
Set the key and workspace in the environment; the CLI never reads or writes a
config file:
```bash
export SIM_API_KEY="sim_…"
export SIM_WORKSPACE="ws_abc123"
sim workflows run wf_7Yb2 --input '{"source":"nightly"}' --output json
```
Create the key in Sim under **Settings → API keys**. Store it as a secret in your
CI provider — never commit it.
`SIM_CONFIG_DIR` relocates both files if you need them somewhere other than
`~/.sim`, such as a runner with no writable home directory.
### GitHub Actions [#github-actions]
```yaml title=".github/workflows/nightly.yml"
jobs:
digest:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g sim
- run: sim workflows run wf_7Yb2 --output json
env:
SIM_API_KEY: ${{ secrets.SIM_API_KEY }}
SIM_WORKSPACE: ${{ vars.SIM_WORKSPACE }}
```
## Several accounts at once [#several-accounts-at-once]
Each profile holds one identity and one set of defaults:
```bash
sim login --profile dev --endpoint http://localhost:3000
sim login --profile prod
sim workflows list --profile dev
sim workflows list --profile prod
```
See [Configuration](/cli/configuration) for how profiles are stored and resolved.
## Self-hosted and non-production deployments [#self-hosted-and-non-production-deployments]
Point the CLI at any deployment with `--endpoint`, then sign in against it:
```bash
sim login --profile local --endpoint http://localhost:3000
```
Save it to avoid repeating the flag:
```bash
sim configure --set-endpoint http://localhost:3000 --profile local
```
## Where the key is stored [#where-the-key-is-stored]
Keys live in `~/.sim/credentials`, written `0600`, separate from the non-secret
`~/.sim/config`. Commit `config` to a dotfiles repo if you like; never
`credentials`.
```ini title="~/.sim/credentials"
[default]
api_key = sim_…
[dev]
api_key = sim_…
```
## Organization audit logs [#organization-audit-logs]
`sim audit-logs` requires a **personal** API key — the kind `sim login` issues.
A workspace-scoped key cannot read organization-level audit logs.
---
# Billing (/cli/billing)
Every command below also accepts the [global options](/cli/commands#global-options).
## Show billing status and current-period credit usage [#show-billing-status-and-current-period-credit-usage]
```bash
sim billing status [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------------------------------- |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
## List credit usage events [#list-credit-usage-events]
```bash
sim billing logs [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--source ` | No | Filter by usage source; sim-chat combines Copilot and workspace chat. Accepted values: `workflow`, `wand`, `sim-chat`, `mcp_copilot`, `mothership_block`, `knowledge-base`, `voice-input`, `enrichment`, `voice-output`. |
| `--period ` | No | Billing period. Accepted values: `1d`, `7d`, `30d`, `all`, `custom`. |
| `--start-date ` | No | Custom period start (ISO 8601). |
| `--end-date ` | No | Custom period end (ISO 8601). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
---
# Overview (/cli/commands)
Every `sim` command follows the same shape:
```bash
sim [sub-resource] [arguments] [options]
```
Resource groups are plural, and each one also accepts its singular spelling —
`sim workflow get` and `sim workflows get` are the same command. `knowledge`
additionally answers to `kb`.
## Global options [#global-options]
These apply to every command, and may be written before or after it.
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------- |
| `-P, --profile ` | Profile to use (env: SIM\_PROFILE). |
| `--endpoint ` | Sim deployment to talk to (env: SIM\_ENDPOINT). |
| `-w, --workspace ` | Workspace to target (env: SIM\_WORKSPACE). |
| `--output ` | Output format for this command. Accepted values: `table`, `json`, `yaml`, `text`. |
## Command groups [#command-groups]
| Group | Description |
| --------------------------------------- | ------------------- |
| [`sim audit-logs`](/cli/audit-logs) | Manage audit logs |
| [`sim billing`](/cli/billing) | Manage billing |
| [`sim credentials`](/cli/credentials) | Manage credentials |
| [`sim custom-tools`](/cli/custom-tools) | Manage custom tools |
| [`sim files`](/cli/files) | Manage files |
| [`sim knowledge`](/cli/knowledge) | Manage knowledge |
| [`sim logs`](/cli/logs) | Manage logs |
| [`sim mcp-servers`](/cli/mcp-servers) | Manage mcp servers |
| [`sim secrets`](/cli/secrets) | Manage secrets |
| [`sim skills`](/cli/skills) | Manage skills |
| [`sim tables`](/cli/tables) | Manage tables |
| [`sim workflows`](/cli/workflows) | Manage workflows |
| [`sim workspaces`](/cli/workspaces) | Manage workspaces |
## Authorize this terminal and store an API key for the profile [#authorize-this-terminal-and-store-an-api-key-for-the-profile]
```bash
sim login [options]
```
**Options**
| Option | Required | Description |
| ----------------- | -------- | -------------------------------------------------------------------- |
| `--scope ` | No | Key space to mint from: platform or copilot. Defaults to `platform`. |
| `--no-browser` | No | Print the URL instead of opening a browser. |
| `-y, --yes` | No | Overwrite an existing profile without prompting. |
## Remove the profile's stored API key [#remove-the-profiles-stored-api-key]
```bash
sim logout [options]
```
**Options**
| Option | Required | Description |
| ------- | -------- | ---------------------------------------------------- |
| `--all` | No | Remove the profile entirely, including its settings. |
## Show the resolved profile and where each setting came from [#show-the-resolved-profile-and-where-each-setting-came-from]
```bash
sim whoami
```
## List the profiles defined in the config and credentials files [#list-the-profiles-defined-in-the-config-and-credentials-files]
```bash
sim profiles
```
Also available as `sim profile`.
## Set a profile's endpoint, default workspace, or output format [#set-a-profiles-endpoint-default-workspace-or-output-format]
```bash
sim configure [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------ |
| `--set-endpoint ` | No | Sim deployment to talk to. |
| `--set-workspace ` | No | Default workspace for workspace-scoped commands. |
| `--set-output ` | No | Default output format (table \| json \| yaml \| text). |
| `--unset ` | No | Remove settings (endpoint, workspace, output). |
---
# Configuration (/cli/configuration)
The CLI has four settings: **endpoint**, **API key**, **workspace**, and **output
format**. Each resolves independently, so a saved default can still be overridden
for a single command.
## Profiles [#profiles]
A profile is one identity plus one set of defaults, in the style of the AWS CLI.
Select one with `-P`, `--profile`, or `SIM_PROFILE`:
```bash
sim workflows list --profile dev
SIM_PROFILE=dev sim workflows list
```
The profile is named `default` when you do not pick one.
```bash
sim profiles # list them; * marks the active one
```
## Setting defaults [#setting-defaults]
```bash
sim configure --set-endpoint http://localhost:3000 --profile dev
sim configure --set-workspace ws_local --profile dev
sim configure --set-output json
```
| Option | What it sets |
| ----------------------- | --------------------------------------------------------- |
| `--set-endpoint ` | The Sim deployment to talk to |
| `--set-workspace ` | Default workspace for workspace-scoped commands |
| `--set-output ` | Default output format: `table`, `json`, `yaml`, or `text` |
| `--unset ` | Remove settings — `endpoint`, `workspace`, or `output` |
Run `sim configure` with no flags to print the profile's stored settings.
API keys are not settable here. Use [`sim login`](/cli/authentication), or
`SIM_API_KEY` for CI.
## Where settings come from [#where-settings-come-from]
Each setting resolves independently, and the first match wins:
| Rank | Source |
| ---- | -------------------------------------------------------------------------- |
| 1 | Command-line flag — `--endpoint`, `--workspace`, `--output` |
| 2 | Environment — `SIM_ENDPOINT`, `SIM_API_KEY`, `SIM_WORKSPACE`, `SIM_OUTPUT` |
| 3 | `~/.sim/config` and `~/.sim/credentials`, for the selected profile |
| 4 | Built-in default — `https://sim.ai` and `table` |
`sim whoami` prints the winning source for each setting:
```bash
sim whoami
```
## The files [#the-files]
Non-secret settings live in `~/.sim/config`. It is safe to commit to a dotfiles
repo:
```ini title="~/.sim/config"
[default]
endpoint = https://sim.ai
workspace = ws_abc123
output = table
[profile dev]
endpoint = http://localhost:3000
workspace = ws_local
```
Keys live in `~/.sim/credentials`, written `0600`:
```ini title="~/.sim/credentials"
[default]
api_key = sim_…
[dev]
api_key = sim_…
```
Section naming follows the AWS convention: `[profile dev]` in config, `[dev]` in
credentials. The `default` profile is `[default]` in both.
## Environment variables [#environment-variables]
| Variable | Effect |
| ---------------------- | -------------------------------------- |
| `SIM_PROFILE` | Profile to use |
| `SIM_ENDPOINT` | Deployment to talk to |
| `SIM_API_KEY` | API key — skips `sim login` entirely |
| `SIM_WORKSPACE` | Workspace to target |
| `SIM_OUTPUT` | Output format |
| `SIM_CONFIG_DIR` | Relocate both files away from `~/.sim` |
| `SIM_CONFIG_FILE` | Relocate only the config file |
| `SIM_CREDENTIALS_FILE` | Relocate only the credentials file |
For CI, set `SIM_API_KEY` and `SIM_WORKSPACE` and nothing needs to touch the
filesystem at all.
## Choosing a workspace [#choosing-a-workspace]
Workspace-scoped commands need a workspace:
```bash
sim tables list --workspace ws_other
sim configure --set-workspace ws_abc123
export SIM_WORKSPACE=ws_abc123
```
`sim billing status`, `sim billing logs`, and `sim audit-logs list` accept
`--all-workspaces` to drop the filter instead. It cannot be combined with
`--workspace`.
## Repairing a bad setting [#repairing-a-bad-setting]
An invalid `output` value fails with the list of accepted formats. A
higher-priority source still wins, so you can repair a profile without editing
the file:
```bash
sim --output table configure --set-output json
```
---
# Credentials (/cli/credentials)
`sim credentials` is also spelled `sim credential`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Disconnect credential [#disconnect-credential]
```bash
sim credentials delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------- |
| `credentialId` | Yes | Credential to disconnect. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## List credential providers [#list-credential-providers]
```bash
sim credentials providers list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the credential provider name. |
## List credentials [#list-credentials]
```bash
sim credentials list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `--type ` | No | Restrict results to this credential type. Accepted values: `oauth`, `service_account`. |
| `--provider-id ` | No | Restrict results to credentials for this integration provider. |
| `--search ` | No | Case-insensitive substring match against the credential display name. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `displayName`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## Create a service-account credential using its discovered provider schema [#create-a-service-account-credential-using-its-discovered-provider-schema]
```bash
sim credentials create [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------------------------------- |
| `providerId` | Yes | Service-account provider to create a credential for |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | --------------------------------------------------------------------- |
| `--name ` | Yes | Name shown for the credential in Sim. |
| `--credentials ` | Yes | Provider credentials as JSON (or @path / @- to read a file or stdin). |
| `--description ` | No | Optional credential description. |
| `--id ` | No | Client-generated credential ID when provider discovery requires it. |
## Create a short-lived link for connecting an OAuth provider [#create-a-short-lived-link-for-connecting-an-oauth-provider]
```bash
sim credentials connect [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------- |
| `providerId` | Yes | OAuth provider to connect |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ----------------------------------------- |
| `--name ` | Yes | Name shown for the new credential in Sim. |
## Create a short-lived link for reconnecting an OAuth credential [#create-a-short-lived-link-for-reconnecting-an-oauth-credential]
```bash
sim credentials reconnect
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ----------------------------------------- |
| `credentialId` | Yes | Existing OAuth credential to re-authorize |
---
# Custom Tools (/cli/custom-tools)
`sim custom-tools` is also spelled `sim custom-tool`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Create custom tool [#create-custom-tool]
```bash
sim custom-tools create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | Yes | Display title, unique within the workspace. |
| `--schema ` | Yes | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | Yes | Tool implementation executed in the sandboxed function runtime. |
## Delete custom tool [#delete-custom-tool]
```bash
sim custom-tools delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Get custom tool [#get-custom-tool]
```bash
sim custom-tools get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
## List custom tools [#list-custom-tools]
```bash
sim custom-tools list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the tool title. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `title`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## Update custom tool [#update-custom-tool]
```bash
sim custom-tools update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | No | New display title for the tool. |
| `--schema ` | No | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | No | Replacement tool implementation. |
---
# Files (/cli/files)
`sim files` is also spelled `sim file`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Delete several files at once [#delete-several-files-at-once]
```bash
sim files batch-delete [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line). |
| `-y, --yes` | No | Skip the confirmation. |
## Create file [#create-file]
```bash
sim files create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | File name, including its extension. Path separators and dot segments are rejected. |
| `--content-type ` | No | MIME type. When omitted, it is inferred from the file extension. |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--content ` | No | Initial file content. Omit or send an empty string for a zero-byte file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. Use an upload session for anything larger. |
| `--encoding ` | No | Encoding of the content field. Accepted values: `utf-8`, `base64`. |
## Create a file folder at a path [#create-a-file-folder-at-a-path]
```bash
sim files folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
## Delete folder [#delete-folder]
```bash
sim files folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
## List folders [#list-folders]
```bash
sim files folders list [options]
```
Also available as `sim files folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
## Rename or move a file folder [#rename-or-move-a-file-folder]
```bash
sim files folders move
```
Also available as `sim files folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
## Delete file [#delete-file]
```bash
sim files delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Show file metadata and sharing status [#show-file-metadata-and-sharing-status]
```bash
sim files describe [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a `DELETE` soft-deleted; `archived` also resolves soft-deleted files, so metadata stays readable before `POST /files/{fileId}/restore`. Authorization is identical for both. Accepted values: `active`, `archived`. |
## Show a file’s share settings [#show-a-files-share-settings]
```bash
sim files share get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
## Enable or disable sharing for a file [#enable-or-disable-sharing-for-a-file]
```bash
sim files share set [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--is-active ` | Yes | Whether the share should resolve. Disabling preserves the token and the whole access configuration, so re-enabling restores the share as it was; enabling rewrites the credentials the resulting mode does not use. Accepted values: `true`, `false`. |
| `--auth-type ` | No | How access to the share is gated. The stored mode is kept when omitted. Enabling `public` clears the stored password and empties `allowedEmails`; `password` empties `allowedEmails`; `email` and `sso` clear the stored password. Accepted values: `public`, `password`, `email`, `sso`. |
| `--password ` | No | Password for a password-gated share. Kept when omitted; enabling `password` with neither a supplied nor a stored password is a 400. |
| `--allowed-emails ` | No | Allowed addresses or `@domain` patterns for email and SSO shares. Kept when omitted; enabling `email` or `sso` with an empty resulting list is a 400. (space-separated, or @path / @- with one value per line). |
## List files [#list-files]
```bash
sim files list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) for live files, `archived` for files a `DELETE` soft-deleted. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too. Accepted values: `active`, `archived`. |
| `--search ` | No | Case-insensitive substring match against the file name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `size`, `uploadedAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## Move files into another folder [#move-files-into-another-folder]
```bash
sim files move [options]
```
Also available as `sim files mv`.
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line). |
| `--to ` | No | Destination folder path; omit for root. |
## Rename a file [#rename-a-file]
```bash
sim files rename [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | --------------------------------------- |
| `--name ` | Yes | New file name, including its extension. |
## Restore file [#restore-file]
```bash
sim files restore create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
## Replace a file’s contents [#replace-a-files-contents]
```bash
sim files set-content [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--content ` | Yes | Complete replacement content for the file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. |
| `--encoding ` | No | Content encoding. Accepted values: `utf-8`, `base64`. |
## Upload a file to the workspace [#upload-a-file-to-the-workspace]
```bash
sim files upload [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------- |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ---------------------------------------- |
| `--folder ` | No | Destination folder path (defaults to /). |
| `--name ` | No | Store it under a different name. |
## Get a file’s content [#get-a-files-content]
```bash
sim files get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------- |
| `fileId` | Yes | File whose content to read |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | --------------------------------------------- |
| `-o, --output-file ` | No | Write content to a file instead of stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
## List file resources and child folders together [#list-file-resources-and-child-folders-together]
```bash
sim files ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
## Create a file directory at a path [#create-a-file-directory-at-a-path]
```bash
sim files mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
---
# Sim CLI (/cli)
`sim` is the command line for Sim. Sign in once, then run workflows, query tables,
move files, search knowledge bases, and read run logs from the terminal. Every
command has a `--output json` mode, so results pipe cleanly into `jq`, cron jobs,
CI pipelines, and any other tool you already use.
## Install [#install]
```bash
npm install -g sim
```
```bash
pnpm add -g sim
```
```bash
bun add -g sim
```
Requires Node.js 20 or newer. Verify with `sim --version`.
To run it without installing, use `npx sim `.
Using Sim as a library instead? See the [TypeScript](/api-reference/typescript)
and [Python](/api-reference/python) SDKs, or the
[HTTP API](/api-reference/getting-started).
## Your first command [#your-first-command]
### Sign in [#sign-in]
```bash
sim login
```
The terminal prints a pairing code and a URL. Approve it in the browser and pick
a workspace. There is no loopback listener, so this works over SSH and in
containers.
See [Authentication](/cli/authentication) for CI keys, multiple accounts, and
self-hosted deployments.
### Check what you are pointed at [#check-what-you-are-pointed-at]
```bash
sim whoami
```
This prints the resolved endpoint, workspace, and output format — and **where
each one came from**. It is the fastest way to explain a surprising result.
### List your workflows [#list-your-workflows]
```bash
sim workflows list
```
```
ID NAME FOLDER DEPLOYED RUNS LAST RUN
wf_7Yb2 Refund triage /Support yes 412 2026-08-15 14:02:11
wf_9Kd4 Weekly digest /Reporting no 18 2026-08-11 09:00:04
```
### Run one [#run-one]
```bash
sim workflows run wf_7Yb2 --input '{"ticketId":"T-4821"}'
```
A workflow must be deployed before it can be run. Deploy from the editor, or
with `sim workflows deploy `.
## How commands are shaped [#how-commands-are-shaped]
Every command reads the same way:
```bash
sim [sub-resource] [arguments] [options]
```
```bash
sim workflows list
sim tables rows query tbl_123 --limit 50
sim knowledge documents upload kb_123 ./handbook.pdf
```
Resource groups are plural, and each also accepts its singular spelling —
`sim workflow get` and `sim workflows get` are the same command. `knowledge`
also answers to `kb`.
Every command accepts `--help`, at any depth:
```bash
sim --help
sim tables --help
sim tables rows query --help
```
## What you can do [#what-you-can-do]
| Group | What it covers |
| ----------------------------------- | ---------------------------------------------------------------- |
| [`workflows`](/cli/workflows) | Run, deploy, roll back, import, export, and organize workflows |
| [`logs`](/cli/logs) | Read run diagnostics, including the full trace tree |
| [`tables`](/cli/tables) | Query, insert, update, and import rows; manage columns and views |
| [`files`](/cli/files) | Upload, download, share, and organize workspace files |
| [`knowledge`](/cli/knowledge) | Search knowledge bases and manage their documents and tags |
| [`skills`](/cli/skills) | Manage agent skills |
| [`mcp-servers`](/cli/mcp-servers) | Manage MCP server connections and their tools |
| [`custom-tools`](/cli/custom-tools) | Manage custom tool definitions |
| [`credentials`](/cli/credentials) | Connect, reconnect, and disconnect integration credentials |
| [`secrets`](/cli/secrets) | Set and remove workspace secrets |
| [`billing`](/cli/billing) | Check plan status and credit usage |
| [`audit-logs`](/cli/audit-logs) | Read organization audit logs |
| [`workspaces`](/cli/workspaces) | Inspect the active workspace and its members |
The [command reference](/cli/commands) documents every subcommand, argument, and
flag, and is generated from the CLI itself.
## Where to go next [#where-to-go-next]
* [Authentication](/cli/authentication) — signing in, API keys for CI, and multiple accounts
* [Configuration](/cli/configuration) — profiles, config files, environment variables, and precedence
* [Output formats](/cli/output) — `table`, `json`, `yaml`, and `text`, and when to use each
* [Scripting](/cli/scripting) — piping, file inputs, exit codes, and automation recipes
* [Troubleshooting](/cli/troubleshooting) — what each error means, and how to resolve it
* [Command reference](/cli/commands) — every command, argument, and flag
---
# Knowledge (/cli/knowledge)
`sim knowledge` is also spelled `sim kb`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Enable or disable every matching document [#enable-or-disable-every-matching-document]
```bash
sim knowledge documents batch-update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
| `--operation ` | Yes | Whether the selected documents become enabled or disabled for search. Accepted values: `enable`, `disable`. |
| `--document ` | No | Documents to update, by identifier. (space-separated, or @path / @- with one value per line). |
| `--select-all` | No | Apply to every document in the knowledge base. |
| `--enabled-filter ` | No | With `selectAll`, restrict the update to documents in this state. Accepted values: `all`, `enabled`, `disabled`. |
## Delete document [#delete-document]
```bash
sim knowledge documents delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Get document [#get-document]
```bash
sim knowledge documents get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
## List documents [#list-documents]
```bash
sim knowledge documents list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--search ` | No | Case-insensitive substring match against the document filename. |
| `--enabled-filter ` | No | Filter by whether documents are enabled for search. Accepted values: `all`, `enabled`, `disabled`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `filename` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `filename`, `fileSize`, `tokenCount`, `chunkCount`, `uploadedAt`, `processingStatus`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--tag-filters ` | No | A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{"tagName":"category","operator":"eq","value":"billing"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored. |
## Update document [#update-document]
```bash
sim knowledge documents update [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filename ` | No | New filename for the document. |
| `--enabled` | No | Whether the document participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
| `--tag1 ` | No | New value for tag slot 1. |
| `--tag2 ` | No | New value for tag slot 2. |
| `--tag3 ` | No | New value for tag slot 3. |
| `--tag4 ` | No | New value for tag slot 4. |
| `--tag5 ` | No | New value for tag slot 5. |
| `--tag6 ` | No | New value for tag slot 6. |
| `--tag7 ` | No | New value for tag slot 7. |
| `--number1 ` | No | New value for number tag slot 1. |
| `--number2 ` | No | New value for number tag slot 2. |
| `--number3 ` | No | New value for number tag slot 3. |
| `--number4 ` | No | New value for number tag slot 4. |
| `--number5 ` | No | New value for number tag slot 5. |
| `--date1 ` | No | New value for date tag slot 1, formatted YYYY-MM-DD. |
| `--date2 ` | No | New value for date tag slot 2, formatted YYYY-MM-DD. |
| `--boolean1` | No | New value for boolean tag slot 1. |
| `--no-boolean1` | No | Send --boolean1 as false. |
| `--boolean2` | No | New value for boolean tag slot 2. |
| `--no-boolean2` | No | Send --boolean2 as false. |
| `--boolean3` | No | New value for boolean tag slot 3. |
| `--no-boolean3` | No | Send --boolean3 as false. |
| `--retry-processing` | No | Requeue a failed or stuck document for processing. Send it alone — no other field may accompany it — and it answers with a queue acknowledgement rather than the document. |
| `--no-retry-processing` | No | Send --retry-processing as false. |
## Upload a document to a knowledge base [#upload-a-document-to-a-knowledge-base]
```bash
sim knowledge documents upload [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ----------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base to upload into |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------ |
| `--name ` | No | Store it under a different name. |
| `--tag ` | No | Document tags, in tag1 through tag7 order. |
| `--recipe ` | No | Document processing recipe. |
| `--lang ` | No | Document language code. |
## Create knowledge base [#create-knowledge-base]
```bash
sim knowledge create [options]
```
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Human-readable knowledge base name. |
| `--description ` | No | Optional knowledge base description. |
| `--chunking-config ` | No | Chunking configuration; defaults are applied when omitted. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
## Create a knowledge folder at a path [#create-a-knowledge-folder-at-a-path]
```bash
sim knowledge folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
## Delete folder [#delete-folder]
```bash
sim knowledge folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
## List folders [#list-folders]
```bash
sim knowledge folders list [options]
```
Also available as `sim knowledge folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
## Rename or move a knowledge folder [#rename-or-move-a-knowledge-folder]
```bash
sim knowledge folders move
```
Also available as `sim knowledge folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
## Delete knowledge base [#delete-knowledge-base]
```bash
sim knowledge delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Get knowledge base [#get-knowledge-base]
```bash
sim knowledge get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
## List knowledge bases [#list-knowledge-bases]
```bash
sim knowledge list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## List tags [#list-tags]
```bash
sim knowledge tags list
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
## Search knowledge [#search-knowledge]
```bash
sim knowledge search [options]
```
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--kb ` | Yes | Knowledge base ID (repeatable) (space-separated, or @path / @- with one value per line). |
| `--query ` | No | Text to search for. |
| `--top-k ` | No | Maximum number of search results to return. Must be a whole number between 1 and 100; the boundary schema only bounds the range, so a fractional value is admitted here and then rejected with 400 during search. |
| `--tag-filters ` | No | Tag filters as \[\{"tagName":"...","operator":"...","value":"..."}] (JSON, or @path / @- to read a file or stdin). |
| `--search-mode ` | No | Search algorithm. Accepted values: `vector`, `hybrid`. |
| `--reranker-enabled` | No | Re-order retrieved chunks with a reranking model before truncating to `topK`. Ignored for a tag-only search, and billed as an additional search unit. Reranking is best-effort — a provider failure falls back to vector ordering, so check `rerankerStatus` on the response. |
| `--no-reranker-enabled` | No | Send --reranker-enabled as false. |
| `--reranker-model ` | No | Reranking model to use when `rerankerEnabled` is true. Defaults to `rerank-v4.0-fast`. Accepted values: `rerank-v4.0-pro`, `rerank-v4.0-fast`, `rerank-v3.5`. |
| `--reranker-input-count ` | No | How many candidate chunks to retrieve before reranking. Defaults to four times `topK`, capped at 100. A larger pool costs more retrieval work but gives the reranker more to choose from. |
## Update knowledge base [#update-knowledge-base]
```bash
sim knowledge update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `--name ` | No | New knowledge base name. |
| `--description ` | No | New knowledge base description. |
| `--chunking-config ` | No | New document chunking configuration. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
## Move a knowledge base to a folder [#move-a-knowledge-base-to-a-folder]
```bash
sim knowledge mv
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
| `folder` | Yes | Folder path; the leading / is optional |
## List knowledge resources and child folders together [#list-knowledge-resources-and-child-folders-together]
```bash
sim knowledge ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
## Create a knowledge directory at a path [#create-a-knowledge-directory-at-a-path]
```bash
sim knowledge mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
---
# Logs (/cli/logs)
`sim logs` is also spelled `sim log`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Show run diagnostics [#show-run-diagnostics]
```bash
sim logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------- |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |
## List logs [#list-logs]
```bash
sim logs list [options]
```
**Options**
| Option | Required | Description |
| --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. An empty entry is rejected. (space-separated, or @path / @- with one value per line). |
| `--trigger ` | No | Comma-separated trigger types to include. An empty entry is rejected. Values are matched exactly and are case-sensitive — every recorded trigger is lowercase, so `API` matches nothing while `api` matches. The vocabulary is open: it covers the core trigger types (`manual`, `api`, `schedule`, `chat`, `webhook`, `mcp`, `copilot`, `workflow`, `custom_block`) and the provider id of any webhook trigger (`slack`, `gmail`, `github`, …), so an unrecognized member is not rejected — it selects no runs. The literal value `all` is a sentinel that disables this filter entirely, so a list containing it returns runs of every trigger type; no real trigger type is named `all`. (space-separated, or @path / @- with one value per line). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--min-duration-ms ` | No | Minimum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--max-duration-ms ` | No | Maximum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--min-cost ` | No | Minimum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--max-cost ` | No | Maximum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--model ` | No | AI model used during execution. |
| `--details ` | No | Response detail level. Accepted values: `basic`, `full`. |
| `--include-trace-spans` | No | Include trace spans in JSON or YAML output (implies full detail). |
| `--include-final-output` | No | Include final output in JSON or YAML output (implies full detail). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--order ` | No | Sort direction by execution start time. This list is sortable only by execution start time, so it takes `order` in place of `sortBy`/`sortOrder`, which it rejects. Accepted values: `asc`, `desc`. |
| `--run-id ` | No | Exact run identifier to match. |
| `--folder ` | No | Folder path; the leading / is optional (space-separated, or @path / @- with one value per line). |
---
# MCP Servers (/cli/mcp-servers)
`sim mcp-servers` is also spelled `sim mcp-server`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Create MCP server [#create-mcp-server]
```bash
sim mcp-servers create [options]
```
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create. Accepted values: `streamable-http`. |
| `--url ` | Yes | Absolute HTTP or HTTPS endpoint URL without `{{ENV_VAR}}` references. It determines server identity and is immutable: delete and recreate the server to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create. |
| `--retries ` | No | Number of retries per request. Applied server-side as 3 when omitted on create. |
| `--enabled` | No | Whether the server tools are available to workflows. Applied server-side as true when omitted on create. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. |
## Delete MCP server [#delete-mcp-server]
```bash
sim mcp-servers delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Get MCP server [#get-mcp-server]
```bash
sim mcp-servers get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
## List MCP servers [#list-mcp-servers]
```bash
sim mcp-servers list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the server name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## List MCP server tools [#list-mcp-server-tools]
```bash
sim mcp-servers tools list [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--refresh` | No | Bypass the short-lived per-workspace tool cache and reconnect under your own credentials. A cached result reflects whichever workspace member last ran discovery, so this is the only way to pick up a tool added since then; it costs a live round trip. |
| `--no-refresh` | No | Send --refresh as false. |
## Update MCP server [#update-mcp-server]
```bash
sim mcp-servers update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | No | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create. Accepted values: `streamable-http`. |
| `--url ` | No | Immutable server URL. When provided, it must equal the current URL; use delete and create to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create. |
| `--retries ` | No | Number of retries per request. Applied server-side as 3 when omitted on create. |
| `--enabled` | No | Whether the server tools are available to workflows. Applied server-side as true when omitted on create. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. |
---
# Output formats (/cli/output)
Every command renders through the same four formats.
| Format | For |
| ------- | ------------------------------------------------- |
| `table` | reading (default) |
| `json` | piping into `jq` |
| `yaml` | piping into anything that reads YAML |
| `text` | shell loops — tab-separated, no header, no colour |
Select one per command, save it to the profile, or set it in the environment:
```bash
sim tables get tbl_123 --output json
sim configure --set-output json
SIM_OUTPUT=yaml sim logs list > logs.yaml
```
`--output` works before or after the command.
## What each format emits [#what-each-format-emits]
`json` and `yaml` emit the API's raw values, not the table's formatting — a
duration stays `1500`, not `"1.5s"`.
`table` formats for reading: timestamps without milliseconds, sizes as `4.2 MB`,
booleans as `yes`/`no`, costs as `$0.0142`. Long cells are clipped to keep rows
on one line; switch to `json` for the full value.
`text` uses the rendered cells, tab-separated, with no header or colour:
```bash
SIM_OUTPUT=text sim files list | while IFS=$'\t' read -r id name folder size type uploader uploaded; do
echo "$id $name"
done
```
An absent value is an em-dash in `table` and an empty field in `text`.
## Reading a run in detail [#reading-a-run-in-detail]
`sim logs get` prints a concise summary. Add `--trace` for the recursive trace
with span inputs, outputs, errors, timing, and cost:
```bash
sim logs get run_123 --trace
```
`json` and `yaml` always carry the complete response, so `--trace` is a no-op
there:
```bash
sim logs get run_123 --output json | jq '.traceSpans'
```
## Exceptions [#exceptions]
`sim profiles` and `sim configure` always print for humans — they report local
configuration, not API data.
`sim workflows export` always emits raw JSON, or YAML when the profile says so,
so that it round-trips through `import`:
```bash
sim workflows export wf_123 > wf.json
sim workflows import --workflow @wf.json
```
---
# Complete reference (/cli/reference)
Every command on one page, generated from the CLI itself. Start at the
[overview](/cli/commands) to browse; this page is for searching and for tools.
Append `.mdx` to any page for its raw Markdown —
[`/cli/reference.mdx`](/cli/reference.mdx) is this page as plain text. The docs
are also published as [`/llms.txt`](/llms.txt) and
[`/llms-full.txt`](/llms-full.txt).
## Global options [#global-options]
These apply to every command, and may be written before or after it.
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------- |
| `-P, --profile ` | Profile to use (env: SIM\_PROFILE). |
| `--endpoint ` | Sim deployment to talk to (env: SIM\_ENDPOINT). |
| `-w, --workspace ` | Workspace to target (env: SIM\_WORKSPACE). |
| `--output ` | Output format for this command. Accepted values: `table`, `json`, `yaml`, `text`. |
## sim login [#sim-login]
Authorize this terminal and store an API key for the profile
```bash
sim login [options]
```
**Options**
| Option | Required | Description |
| ----------------- | -------- | -------------------------------------------------------------------- |
| `--scope ` | No | Key space to mint from: platform or copilot. Defaults to `platform`. |
| `--no-browser` | No | Print the URL instead of opening a browser. |
| `-y, --yes` | No | Overwrite an existing profile without prompting. |
## sim logout [#sim-logout]
Remove the profile's stored API key
```bash
sim logout [options]
```
**Options**
| Option | Required | Description |
| ------- | -------- | ---------------------------------------------------- |
| `--all` | No | Remove the profile entirely, including its settings. |
## sim whoami [#sim-whoami]
Show the resolved profile and where each setting came from
```bash
sim whoami
```
## sim profiles [#sim-profiles]
List the profiles defined in the config and credentials files
```bash
sim profiles
```
Also available as `sim profile`.
## sim configure [#sim-configure]
Set a profile's endpoint, default workspace, or output format
```bash
sim configure [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------ |
| `--set-endpoint ` | No | Sim deployment to talk to. |
| `--set-workspace ` | No | Default workspace for workspace-scoped commands. |
| `--set-output ` | No | Default output format (table \| json \| yaml \| text). |
| `--unset ` | No | Remove settings (endpoint, workspace, output). |
## sim audit-logs [#sim-audit-logs]
Also spelled `sim audit-log`.
### sim audit-logs get [#sim-audit-logs-get]
Get Audit Log
```bash
sim audit-logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Audit-log entry identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------- |
| `--organization ` | Yes | Organization ID (personal API key required). |
### sim audit-logs list [#sim-audit-logs-list]
List Audit Logs
```bash
sim audit-logs list [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--action ` | No | Filter by exact action name. |
| `--resource-type ` | No | Filter by resource type. Accepts a comma-separated set; members are trimmed and deduplicated, and member order affects neither the result nor the cursor. |
| `--resource-id ` | No | Filter by exact resource identifier. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--include-departed` | No | Include actions by users who have left the organization. |
| `--no-include-departed` | No | Send --include-departed as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--organization ` | Yes | Organization ID (personal API key required). |
| `--actor-email ` | No | Filter by actor email address. |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
## sim billing [#sim-billing]
### sim billing status [#sim-billing-status]
Show billing status and current-period credit usage
```bash
sim billing status [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------------------------------- |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
### sim billing logs [#sim-billing-logs]
List credit usage events
```bash
sim billing logs [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--source ` | No | Filter by usage source; sim-chat combines Copilot and workspace chat. Accepted values: `workflow`, `wand`, `sim-chat`, `mcp_copilot`, `mothership_block`, `knowledge-base`, `voice-input`, `enrichment`, `voice-output`. |
| `--period ` | No | Billing period. Accepted values: `1d`, `7d`, `30d`, `all`, `custom`. |
| `--start-date ` | No | Custom period start (ISO 8601). |
| `--end-date ` | No | Custom period end (ISO 8601). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--all-workspaces` | No | Do not filter to the configured workspace (personal API key required for account-wide access). |
## sim credentials [#sim-credentials]
Also spelled `sim credential`.
### sim credentials delete [#sim-credentials-delete]
Disconnect Credential
```bash
sim credentials delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------- |
| `credentialId` | Yes | Credential to disconnect. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim credentials providers list [#sim-credentials-providers-list]
List Credential Providers
```bash
sim credentials providers list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the credential provider name. |
### sim credentials list [#sim-credentials-list]
List Credentials
```bash
sim credentials list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `--type ` | No | Restrict results to this credential type. Accepted values: `oauth`, `service_account`. |
| `--provider-id ` | No | Restrict results to credentials for this integration provider. |
| `--search ` | No | Case-insensitive substring match against the credential display name. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `displayName`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim credentials create [#sim-credentials-create]
Create a service-account credential using its discovered provider schema
```bash
sim credentials create [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------------------------------- |
| `providerId` | Yes | Service-account provider to create a credential for |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | --------------------------------------------------------------------- |
| `--name ` | Yes | Name shown for the credential in Sim. |
| `--credentials ` | Yes | Provider credentials as JSON (or @path / @- to read a file or stdin). |
| `--description ` | No | Optional credential description. |
| `--id ` | No | Client-generated credential ID when provider discovery requires it. |
### sim credentials connect [#sim-credentials-connect]
Create a short-lived link for connecting an OAuth provider
```bash
sim credentials connect [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------- |
| `providerId` | Yes | OAuth provider to connect |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ----------------------------------------- |
| `--name ` | Yes | Name shown for the new credential in Sim. |
### sim credentials reconnect [#sim-credentials-reconnect]
Create a short-lived link for reconnecting an OAuth credential
```bash
sim credentials reconnect
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ----------------------------------------- |
| `credentialId` | Yes | Existing OAuth credential to re-authorize |
## sim custom-tools [#sim-custom-tools]
Also spelled `sim custom-tool`.
### sim custom-tools create [#sim-custom-tools-create]
Create Custom Tool
```bash
sim custom-tools create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | Yes | Display title, unique within the workspace. |
| `--schema ` | Yes | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | Yes | Tool implementation executed in the sandboxed function runtime. |
### sim custom-tools delete [#sim-custom-tools-delete]
Delete Custom Tool
```bash
sim custom-tools delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim custom-tools get [#sim-custom-tools-get]
Get Custom Tool
```bash
sim custom-tools get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
### sim custom-tools list [#sim-custom-tools-list]
List Custom Tools
```bash
sim custom-tools list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the tool title. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `title`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim custom-tools update [#sim-custom-tools-update]
Update Custom Tool
```bash
sim custom-tools update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------ |
| `id` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | No | New display title for the tool. |
| `--schema ` | No | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | No | Replacement tool implementation. |
## sim files [#sim-files]
Also spelled `sim file`.
### sim files batch-delete [#sim-files-batch-delete]
Delete several files at once
```bash
sim files batch-delete [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line). |
| `-y, --yes` | No | Skip the confirmation. |
### sim files create [#sim-files-create]
Create File
```bash
sim files create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | File name, including its extension. Path separators and dot segments are rejected. |
| `--content-type ` | No | MIME type. When omitted, it is inferred from the file extension. |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--content ` | No | Initial file content. Omit or send an empty string for a zero-byte file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. Use an upload session for anything larger. |
| `--encoding ` | No | Encoding of the content field. Accepted values: `utf-8`, `base64`. |
### sim files folders create [#sim-files-folders-create]
Create a file folder at a path
```bash
sim files folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
### sim files folders delete [#sim-files-folders-delete]
Delete Folder
```bash
sim files folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
### sim files folders list [#sim-files-folders-list]
List Folders
```bash
sim files folders list [options]
```
Also available as `sim files folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim files folders move [#sim-files-folders-move]
Rename or move a file folder
```bash
sim files folders move
```
Also available as `sim files folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
### sim files delete [#sim-files-delete]
Delete File
```bash
sim files delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim files describe [#sim-files-describe]
Show file metadata and sharing status
```bash
sim files describe [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a `DELETE` soft-deleted; `archived` also resolves soft-deleted files, so metadata stays readable before `POST /files/{fileId}/restore`. Authorization is identical for both. Accepted values: `active`, `archived`. |
### sim files share get [#sim-files-share-get]
Show a file’s share settings
```bash
sim files share get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
### sim files share set [#sim-files-share-set]
Enable or disable sharing for a file
```bash
sim files share set [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--is-active ` | Yes | Whether the share should resolve. Disabling preserves the token and the whole access configuration, so re-enabling restores the share as it was; enabling rewrites the credentials the resulting mode does not use. Accepted values: `true`, `false`. |
| `--auth-type ` | No | How access to the share is gated. The stored mode is kept when omitted. Enabling `public` clears the stored password and empties `allowedEmails`; `password` empties `allowedEmails`; `email` and `sso` clear the stored password. Accepted values: `public`, `password`, `email`, `sso`. |
| `--password ` | No | Password for a password-gated share. Kept when omitted; enabling `password` with neither a supplied nor a stored password is a 400. |
| `--allowed-emails ` | No | Allowed addresses or `@domain` patterns for email and SSO shares. Kept when omitted; enabling `email` or `sso` with an empty resulting list is a 400. (space-separated, or @path / @- with one value per line). |
### sim files list [#sim-files-list]
List Files
```bash
sim files list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) for live files, `archived` for files a `DELETE` soft-deleted. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too. Accepted values: `active`, `archived`. |
| `--search ` | No | Case-insensitive substring match against the file name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `size`, `uploadedAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim files move [#sim-files-move]
Move files into another folder
```bash
sim files move [options]
```
Also available as `sim files mv`.
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line). |
| `--to ` | No | Destination folder path; omit for root. |
### sim files rename [#sim-files-rename]
Rename a file
```bash
sim files rename [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | --------------------------------------- |
| `--name ` | Yes | New file name, including its extension. |
### sim files restore create [#sim-files-restore-create]
Restore File
```bash
sim files restore create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
### sim files set-content [#sim-files-set-content]
Replace a file’s contents
```bash
sim files set-content [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--content ` | Yes | Complete replacement content for the file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. |
| `--encoding ` | No | Content encoding. Accepted values: `utf-8`, `base64`. |
### sim files upload [#sim-files-upload]
Upload a file to the workspace
```bash
sim files upload [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------- |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ---------------------------------------- |
| `--folder ` | No | Destination folder path (defaults to /). |
| `--name ` | No | Store it under a different name. |
### sim files get [#sim-files-get]
Get a file’s content
```bash
sim files get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------- |
| `fileId` | Yes | File whose content to read |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | --------------------------------------------- |
| `-o, --output-file ` | No | Write content to a file instead of stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
### sim files ls [#sim-files-ls]
List file resources and child folders together
```bash
sim files ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
### sim files mkdir [#sim-files-mkdir]
Create a file directory at a path
```bash
sim files mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim knowledge [#sim-knowledge]
Also spelled `sim kb`.
### sim knowledge documents batch-update [#sim-knowledge-documents-batch-update]
Enable or disable every matching document
```bash
sim knowledge documents batch-update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
| `--operation ` | Yes | Whether the selected documents become enabled or disabled for search. Accepted values: `enable`, `disable`. |
| `--document ` | No | Documents to update, by identifier. (space-separated, or @path / @- with one value per line). |
| `--select-all` | No | Apply to every document in the knowledge base. |
| `--enabled-filter ` | No | With `selectAll`, restrict the update to documents in this state. Accepted values: `all`, `enabled`, `disabled`. |
### sim knowledge documents delete [#sim-knowledge-documents-delete]
Delete Document
```bash
sim knowledge documents delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim knowledge documents get [#sim-knowledge-documents-get]
Get Document
```bash
sim knowledge documents get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
### sim knowledge documents list [#sim-knowledge-documents-list]
List Documents
```bash
sim knowledge documents list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--search ` | No | Case-insensitive substring match against the document filename. |
| `--enabled-filter ` | No | Filter by whether documents are enabled for search. Accepted values: `all`, `enabled`, `disabled`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `filename` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `filename`, `fileSize`, `tokenCount`, `chunkCount`, `uploadedAt`, `processingStatus`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--tag-filters ` | No | A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{"tagName":"category","operator":"eq","value":"billing"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored. |
### sim knowledge documents update [#sim-knowledge-documents-update]
Update Document
```bash
sim knowledge documents update [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filename ` | No | New filename for the document. |
| `--enabled` | No | Whether the document participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
| `--tag1 ` | No | New value for tag slot 1. |
| `--tag2 ` | No | New value for tag slot 2. |
| `--tag3 ` | No | New value for tag slot 3. |
| `--tag4 ` | No | New value for tag slot 4. |
| `--tag5 ` | No | New value for tag slot 5. |
| `--tag6 ` | No | New value for tag slot 6. |
| `--tag7 ` | No | New value for tag slot 7. |
| `--number1 ` | No | New value for number tag slot 1. |
| `--number2 ` | No | New value for number tag slot 2. |
| `--number3 ` | No | New value for number tag slot 3. |
| `--number4 ` | No | New value for number tag slot 4. |
| `--number5 ` | No | New value for number tag slot 5. |
| `--date1 ` | No | New value for date tag slot 1, formatted YYYY-MM-DD. |
| `--date2 ` | No | New value for date tag slot 2, formatted YYYY-MM-DD. |
| `--boolean1` | No | New value for boolean tag slot 1. |
| `--no-boolean1` | No | Send --boolean1 as false. |
| `--boolean2` | No | New value for boolean tag slot 2. |
| `--no-boolean2` | No | Send --boolean2 as false. |
| `--boolean3` | No | New value for boolean tag slot 3. |
| `--no-boolean3` | No | Send --boolean3 as false. |
| `--retry-processing` | No | Requeue a failed or stuck document for processing. Send it alone — no other field may accompany it — and it answers with a queue acknowledgement rather than the document. |
| `--no-retry-processing` | No | Send --retry-processing as false. |
### sim knowledge documents upload [#sim-knowledge-documents-upload]
Upload a document to a knowledge base
```bash
sim knowledge documents upload [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ----------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base to upload into |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------ |
| `--name ` | No | Store it under a different name. |
| `--tag ` | No | Document tags, in tag1 through tag7 order. |
| `--recipe ` | No | Document processing recipe. |
| `--lang ` | No | Document language code. |
### sim knowledge create [#sim-knowledge-create]
Create Knowledge Base
```bash
sim knowledge create [options]
```
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Human-readable knowledge base name. |
| `--description ` | No | Optional knowledge base description. |
| `--chunking-config ` | No | Chunking configuration; defaults are applied when omitted. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim knowledge folders create [#sim-knowledge-folders-create]
Create a knowledge folder at a path
```bash
sim knowledge folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
### sim knowledge folders delete [#sim-knowledge-folders-delete]
Delete Folder
```bash
sim knowledge folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
### sim knowledge folders list [#sim-knowledge-folders-list]
List Folders
```bash
sim knowledge folders list [options]
```
Also available as `sim knowledge folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim knowledge folders move [#sim-knowledge-folders-move]
Rename or move a knowledge folder
```bash
sim knowledge folders move
```
Also available as `sim knowledge folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
### sim knowledge delete [#sim-knowledge-delete]
Delete Knowledge Base
```bash
sim knowledge delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim knowledge get [#sim-knowledge-get]
Get Knowledge Base
```bash
sim knowledge get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
### sim knowledge list [#sim-knowledge-list]
List Knowledge Bases
```bash
sim knowledge list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim knowledge tags list [#sim-knowledge-tags-list]
List Tags
```bash
sim knowledge tags list
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
### sim knowledge search [#sim-knowledge-search]
Search Knowledge
```bash
sim knowledge search [options]
```
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--kb ` | Yes | Knowledge base ID (repeatable) (space-separated, or @path / @- with one value per line). |
| `--query ` | No | Text to search for. |
| `--top-k ` | No | Maximum number of search results to return. Must be a whole number between 1 and 100; the boundary schema only bounds the range, so a fractional value is admitted here and then rejected with 400 during search. |
| `--tag-filters ` | No | Tag filters as \[\{"tagName":"...","operator":"...","value":"..."}] (JSON, or @path / @- to read a file or stdin). |
| `--search-mode ` | No | Search algorithm. Accepted values: `vector`, `hybrid`. |
| `--reranker-enabled` | No | Re-order retrieved chunks with a reranking model before truncating to `topK`. Ignored for a tag-only search, and billed as an additional search unit. Reranking is best-effort — a provider failure falls back to vector ordering, so check `rerankerStatus` on the response. |
| `--no-reranker-enabled` | No | Send --reranker-enabled as false. |
| `--reranker-model ` | No | Reranking model to use when `rerankerEnabled` is true. Defaults to `rerank-v4.0-fast`. Accepted values: `rerank-v4.0-pro`, `rerank-v4.0-fast`, `rerank-v3.5`. |
| `--reranker-input-count ` | No | How many candidate chunks to retrieve before reranking. Defaults to four times `topK`, capped at 100. A larger pool costs more retrieval work but gives the reranker more to choose from. |
### sim knowledge update [#sim-knowledge-update]
Update Knowledge Base
```bash
sim knowledge update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `--name ` | No | New knowledge base name. |
| `--description ` | No | New knowledge base description. |
| `--chunking-config ` | No | New document chunking configuration. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim knowledge mv [#sim-knowledge-mv]
Move a knowledge base to a folder
```bash
sim knowledge mv
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `id` | Yes | Unique knowledge base identifier. |
| `folder` | Yes | Folder path; the leading / is optional |
### sim knowledge ls [#sim-knowledge-ls]
List knowledge resources and child folders together
```bash
sim knowledge ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
### sim knowledge mkdir [#sim-knowledge-mkdir]
Create a knowledge directory at a path
```bash
sim knowledge mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim logs [#sim-logs]
Also spelled `sim log`.
### sim logs get [#sim-logs-get]
Show run diagnostics
```bash
sim logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------- |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |
### sim logs list [#sim-logs-list]
List Logs
```bash
sim logs list [options]
```
**Options**
| Option | Required | Description |
| --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. An empty entry is rejected. (space-separated, or @path / @- with one value per line). |
| `--trigger ` | No | Comma-separated trigger types to include. An empty entry is rejected. Values are matched exactly and are case-sensitive — every recorded trigger is lowercase, so `API` matches nothing while `api` matches. The vocabulary is open: it covers the core trigger types (`manual`, `api`, `schedule`, `chat`, `webhook`, `mcp`, `copilot`, `workflow`, `custom_block`) and the provider id of any webhook trigger (`slack`, `gmail`, `github`, …), so an unrecognized member is not rejected — it selects no runs. The literal value `all` is a sentinel that disables this filter entirely, so a list containing it returns runs of every trigger type; no real trigger type is named `all`. (space-separated, or @path / @- with one value per line). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--min-duration-ms ` | No | Minimum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--max-duration-ms ` | No | Maximum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--min-cost ` | No | Minimum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--max-cost ` | No | Maximum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--model ` | No | AI model used during execution. |
| `--details ` | No | Response detail level. Accepted values: `basic`, `full`. |
| `--include-trace-spans` | No | Include trace spans in JSON or YAML output (implies full detail). |
| `--include-final-output` | No | Include final output in JSON or YAML output (implies full detail). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--order ` | No | Sort direction by execution start time. This list is sortable only by execution start time, so it takes `order` in place of `sortBy`/`sortOrder`, which it rejects. Accepted values: `asc`, `desc`. |
| `--run-id ` | No | Exact run identifier to match. |
| `--folder ` | No | Folder path; the leading / is optional (space-separated, or @path / @- with one value per line). |
## sim mcp-servers [#sim-mcp-servers]
Also spelled `sim mcp-server`.
### sim mcp-servers create [#sim-mcp-servers-create]
Create MCP Server
```bash
sim mcp-servers create [options]
```
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create. Accepted values: `streamable-http`. |
| `--url ` | Yes | Absolute HTTP or HTTPS endpoint URL without `{{ENV_VAR}}` references. It determines server identity and is immutable: delete and recreate the server to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create. |
| `--retries ` | No | Number of retries per request. Applied server-side as 3 when omitted on create. |
| `--enabled` | No | Whether the server tools are available to workflows. Applied server-side as true when omitted on create. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. |
### sim mcp-servers delete [#sim-mcp-servers-delete]
Delete MCP Server
```bash
sim mcp-servers delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim mcp-servers get [#sim-mcp-servers-get]
Get MCP Server
```bash
sim mcp-servers get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
### sim mcp-servers list [#sim-mcp-servers-list]
List MCP Servers
```bash
sim mcp-servers list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the server name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim mcp-servers tools list [#sim-mcp-servers-tools-list]
List MCP Server Tools
```bash
sim mcp-servers tools list [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--refresh` | No | Bypass the short-lived per-workspace tool cache and reconnect under your own credentials. A cached result reflects whichever workspace member last ran discovery, so this is the only way to pick up a tool added since then; it costs a live round trip. |
| `--no-refresh` | No | Send --refresh as false. |
### sim mcp-servers update [#sim-mcp-servers-update]
Update MCP Server
```bash
sim mcp-servers update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ----------------------------- |
| `id` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | No | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create. Accepted values: `streamable-http`. |
| `--url ` | No | Immutable server URL. When provided, it must equal the current URL; use delete and create to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create. |
| `--retries ` | No | Number of retries per request. Applied server-side as 3 when omitted on create. |
| `--enabled` | No | Whether the server tools are available to workflows. Applied server-side as true when omitted on create. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. |
## sim secrets [#sim-secrets]
Also spelled `sim secret`.
### sim secrets delete [#sim-secrets-delete]
Delete Secret
```bash
sim secrets delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------- |
| `name` | Yes | Secret to create, replace, or delete. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | Yes | Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace. Accepted values: `workspace`, `personal`. |
| `-y, --yes` | No | Skip the confirmation. |
### sim secrets list [#sim-secrets-list]
List Secrets
```bash
sim secrets list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Restrict results to one ownership scope. Accepted values: `workspace`, `personal`. |
| `--search ` | No | Case-insensitive substring match against the secret name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim secrets set [#sim-secrets-set]
Create or replace a named secret
```bash
sim secrets set [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------------- |
| `name` | Yes | Secret name, as referenced in workflows |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------- |
| `--scope ` | Yes | Secret ownership scope. Accepted values: `workspace`, `personal`. |
| `--value ` | No | Secret value; visible to shell history when supplied directly. |
## sim skills [#sim-skills]
Also spelled `sim skill`.
### sim skills create [#sim-skills-create]
Create Skill
```bash
sim skills create [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--name ` | Yes | Kebab-case name, unique within the workspace and not reserved by a built-in skill. |
| `--description ` | Yes | One-line summary of when the skill applies. |
| `--content ` | Yes | Skill body containing the instructions given to the agent. |
### sim skills delete [#sim-skills-delete]
Delete Skill
```bash
sim skills delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim skills get [#sim-skills-get]
Get Skill
```bash
sim skills get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
### sim skills list [#sim-skills-list]
List Skills
```bash
sim skills list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the skill name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim skills update [#sim-skills-update]
Update Skill
```bash
sim skills update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ----------------------------------------------- |
| `--name ` | No | New kebab-case skill name. |
| `--description ` | No | New one-line summary of when the skill applies. |
| `--content ` | No | Replacement skill body. |
## sim tables [#sim-tables]
Also spelled `sim table`.
### sim tables columns create [#sim-tables-columns-create]
Add Column
```bash
sim tables columns create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ------------------------------------------------------------------------ |
| `--column ` | Yes | Column definition to add. (JSON, or @path / @- to read a file or stdin). |
### sim tables columns delete [#sim-tables-columns-delete]
Delete Column
```bash
sim tables columns delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ----------------------------- |
| `--column-name ` | Yes | Name of the column to delete. |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables columns run [#sim-tables-columns-run]
Run a column’s workflow
```bash
sim tables columns run [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--group-ids ` | Yes | Workflow or enrichment groups to run. (space-separated, or @path / @- with one value per line). |
| `--run-mode ` | No | Whether to run all or only incomplete cells. Accepted values: `all`, `incomplete`. |
| `--row-ids ` | No | Explicit row subset to run. (space-separated, or @path / @- with one value per line). |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--exclude-row-ids ` | No | Rows excluded from a select-all run scope. (space-separated, or @path / @- with one value per line). |
| `--limit ` | No | Optional cap on eligible rows to run. (JSON, or @path / @- to read a file or stdin). |
### sim tables columns update [#sim-tables-columns-update]
Update Column
```bash
sim tables columns update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------- |
| `--column-name ` | Yes | Current name of the column to update. |
| `--updates ` | Yes | Mutable column fields. (JSON, or @path / @- to read a file or stdin). |
### sim tables groups create [#sim-tables-groups-create]
Add Workflow Group
```bash
sim tables groups create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `--group ` | Yes | Workflow or enrichment producer definition. (JSON, or @path / @- to read a file or stdin). |
| `--output-columns ` | Yes | Columns created for producer outputs. (JSON, or @path / @- to read a file or stdin). |
| `--auto-run` | No | Whether to schedule existing rows after group creation. |
| `--no-auto-run` | No | Send --auto-run as false. |
### sim tables groups delete [#sim-tables-groups-delete]
Delete Workflow Group
```bash
sim tables groups delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------- |
| `--group-id ` | Yes | Workflow group to delete. |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables groups list [#sim-tables-groups-list]
List Workflow Groups
```bash
sim tables groups list
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
### sim tables groups update [#sim-tables-groups-update]
Update Workflow Group
```bash
sim tables groups update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--group-id ` | Yes | Workflow group to update. |
| `--workflow-id ` | No | Replacement backing workflow identifier. |
| `--name ` | No | Replacement workflow-group display name. |
| `--dependencies ` | No | Replacement input dependencies. (JSON, or @path / @- to read a file or stdin). |
| `--outputs ` | No | Replacement producer outputs. (JSON, or @path / @- to read a file or stdin). |
| `--new-output-columns ` | No | Columns to add for new outputs. (JSON, or @path / @- to read a file or stdin). |
| `--mapping-updates ` | No | Existing output-column mapping changes. (JSON, or @path / @- to read a file or stdin). |
| `--input-mappings ` | No | Replacement workflow input mappings. (JSON, or @path / @- to read a file or stdin). |
| `--deployment-mode ` | No | Replacement workflow execution mode. Accepted values: `live`, `deployed`. |
| `--type ` | No | Workflow-group producer type. Must match the group's stored type — a group's producer cannot be changed after creation. Accepted values: `manual`, `enrichment`. |
| `--auto-run` | No | Replacement automatic-run setting. |
| `--no-auto-run` | No | Send --auto-run as false. |
### sim tables exports cancel [#sim-tables-exports-cancel]
Cancel Table Export
```bash
sim tables exports cancel
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
### sim tables exports create [#sim-tables-exports-create]
Create Table Export
```bash
sim tables exports create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------ | -------- | --------------------------------------------------- |
| `--format ` | No | Export file format. Accepted values: `csv`, `json`. |
### sim tables exports get [#sim-tables-exports-get]
Get Table Export
```bash
sim tables exports get
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
### sim tables exports download [#sim-tables-exports-download]
Get the download URL for a finished export
```bash
sim tables exports download
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
### sim tables imports cancel [#sim-tables-imports-cancel]
Cancel Table Import
```bash
sim tables imports cancel
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `importId` | Yes | Unique table-import identifier. |
### sim tables imports get [#sim-tables-imports-get]
Get Table Import
```bash
sim tables imports get
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `importId` | Yes | Unique table-import identifier. |
### sim tables cancel-runs [#sim-tables-cancel-runs]
Stop every running column job
```bash
sim tables cancel-runs [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | Yes | Whether to cancel across the table or one row. Accepted values: `all`, `row`. |
| `--row-id ` | No | Row whose runs should be canceled for row scope. |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--exclude-row-ids ` | No | Rows excluded from an all-scope cancellation. (space-separated, or @path / @- with one value per line). |
### sim tables create [#sim-tables-create]
Create Table
```bash
sim tables create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Identifier: letters, numbers, and underscores; cannot start with a number. |
| `--description ` | No | Optional table description. |
| `--schema ` | Yes | Table schema: \{"columns":\[\{"name":"email","type":"string"}]} (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim tables folders create [#sim-tables-folders-create]
Create a table folder at a path
```bash
sim tables folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
### sim tables folders delete [#sim-tables-folders-delete]
Delete Folder
```bash
sim tables folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables folders list [#sim-tables-folders-list]
List Folders
```bash
sim tables folders list [options]
```
Also available as `sim tables folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim tables folders move [#sim-tables-folders-move]
Rename or move a table folder
```bash
sim tables folders move
```
Also available as `sim tables folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
### sim tables rows create [#sim-tables-rows-create]
Create Rows
```bash
sim tables rows create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------- |
| `--data ` | No | One row keyed by column name (JSON, or @path / @-; choose exactly one body flag). |
| `--rows ` | No | Several rows keyed by column name (JSON, or @path / @-; choose exactly one body flag). |
### sim tables rows delete [#sim-tables-rows-delete]
Delete Row
```bash
sim tables rows delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ---------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `rowId` | Yes | Unique table row identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables rows batch-delete [#sim-tables-rows-batch-delete]
Delete rows matching a filter, or an explicit list of ids
```bash
sim tables rows batch-delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--row ` | No | Explicit row identifiers to delete. (space-separated, or @path / @- with one value per line). |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables rows find [#sim-tables-rows-find]
Find rows matching a predicate
```bash
sim tables rows find [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--q ` | Yes | Value to find. |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--sort ` | No | Ordered sort keys: \[\{"field":"createdAt","direction":"desc"}] (direction: asc or desc) (JSON, or @path / @- to read a file or stdin). |
### sim tables rows get [#sim-tables-rows-get]
Get Row
```bash
sim tables rows get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ---------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `rowId` | Yes | Unique table row identifier. |
### sim tables rows list [#sim-tables-rows-list]
List Rows
```bash
sim tables rows list [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim tables rows query [#sim-tables-rows-query]
Query Rows
```bash
sim tables rows query [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--sort ` | No | Ordered sort keys: \[\{"field":"createdAt","direction":"desc"}] (direction: asc or desc) (JSON, or @path / @- to read a file or stdin). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim tables rows enrich [#sim-tables-rows-enrich]
Run one row’s enrichment group
```bash
sim tables rows enrich
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------------------ |
| `tableId` | Yes | Unique table identifier. |
| `rowId` | Yes | Unique table row identifier. |
| `groupId` | Yes | Workflow or enrichment group to run. |
### sim tables rows batch-update [#sim-tables-rows-batch-update]
Update every row matching a filter
```bash
sim tables rows batch-update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filter ` | Yes | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--data ` | Yes | Row-data patch applied to every matching row. (JSON, or @path / @- to read a file or stdin). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables rows update [#sim-tables-rows-update]
Update Row
```bash
sim tables rows update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ---------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `rowId` | Yes | Unique table row identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------- |
| `--data ` | Yes | Partial row-data patch keyed by column name. (JSON, or @path / @- to read a file or stdin). |
### sim tables views create [#sim-tables-views-create]
Create View
```bash
sim tables views create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | --------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Saved-view display name. |
| `--config ` | Yes | Saved filter, sort, and column-layout configuration. (JSON, or @path / @- to read a file or stdin). |
### sim tables views delete [#sim-tables-views-delete]
Delete View
```bash
sim tables views delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ----------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `viewId` | Yes | Unique saved-view identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables views get [#sim-tables-views-get]
Get View
```bash
sim tables views get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ----------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `viewId` | Yes | Unique saved-view identifier. |
### sim tables views list [#sim-tables-views-list]
List Views
```bash
sim tables views list
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
### sim tables views update [#sim-tables-views-update]
Update View
```bash
sim tables views update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ----------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `viewId` | Yes | Unique saved-view identifier. |
**Options**
| Option | Required | Description |
| ------------------------------ | -------- | ------------------------------------------------------------------------------------------------ |
| `--name ` | No | Replacement saved-view display name. |
| `--config ` | No | Complete replacement saved-view configuration. (JSON, or @path / @- to read a file or stdin). |
| `--config-patch ` | No | Saved-view configuration fields to shallow-merge. (JSON, or @path / @- to read a file or stdin). |
| `--is-default` | No | Whether to promote this view to the table default. |
| `--no-is-default` | No | Send --is-default as false. |
### sim tables delete [#sim-tables-delete]
Delete Table
```bash
sim tables delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim tables get [#sim-tables-get]
Get Table
```bash
sim tables get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
### sim tables list [#sim-tables-list]
List Tables
```bash
sim tables list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim tables count create [#sim-tables-count-create]
Count Rows
```bash
sim tables count create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| --------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--predicate ` | No | Recursive predicate tree. Each group node is exactly one non-empty `all` or `any` array whose members are further groups or `{ field, op, value }` conditions; the root must be a group, not a bare condition. At most 100 members per group, 10 levels of nesting, and 500 nodes in total. The negating operators include nulls: `ne`, `nin`, `ncontains`, `nlike`, and `nilike` match rows whose column is null or absent, so "not X" is not the complement of "X" over a nullable column. That holds for every column type, multi-select included. To exclude nulls, `all`-combine the negation with `isNotEmpty` (multi-select) or `isNotNull`. Comparison: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. Membership: `in`, `nin` (array operand). Emptiness: `isEmpty`, `isNotEmpty`, `isNull`, `isNotNull` (no operand). Substring, always case-insensitive, operand matched literally: `contains`, `ncontains`, `startsWith`, `endsWith`. Pattern: `like`/`nlike` (case-sensitive), `ilike`/`nilike` (case-insensitive). **`*` is the only wildcard** and stands for any run of characters; `%`, `_`, and backslash match themselves. Use `like: "Hi*"`, not `like: "Hi%"`. A `select` column compares by option id and restricts its operators: single-select accepts `eq`, `ne`, `in`, `nin`; multi-select accepts `contains`, `ncontains`. Option names are accepted as operands and resolved to ids. (JSON, or @path / @- to read a file or stdin). |
### sim tables update [#sim-tables-update]
Update Table
```bash
sim tables update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------------------- |
| `--name ` | No | Identifier: letters, numbers, and underscores; cannot start with a number. |
| `--description ` | No | Replacement table description, or null to clear it. |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim tables mv [#sim-tables-mv]
Move a table to a folder
```bash
sim tables mv
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | -------------------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `folder` | Yes | Folder path; the leading / is optional |
### sim tables upsert [#sim-tables-upsert]
Insert a row, or update the one that conflicts on a unique column
```bash
sim tables upsert [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--data ` | Yes | Complete set of row cells keyed by column name. On the update branch this REPLACES the matched row: any column not present here is cleared, unlike the merging `PATCH /api/v2/tables/{tableId}/rows/{rowId}`. (JSON, or @path / @- to read a file or stdin). |
| `--on ` | No | Unique column to resolve the conflict against. |
### sim tables import [#sim-tables-import]
Import a CSV, into a new table by default
```bash
sim tables import [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------------------------- |
| `path` | No | Local CSV file to import; omit when using --file-id |
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `--name ` | No | Identifier for the new table: letters, numbers, and underscores; defaults to the sanitized file name. |
| `--table-id ` | No | Import into this existing table instead of creating one. |
| `--mode ` | No | How to write into --table-id (default: append). Accepted values: `append`, `replace`. |
| `--folder ` | No | Folder path for the new table. |
| `--file-id ` | No | Import a file already in the workspace instead of a local path. |
| `--mapping ` | No | Column mapping (--table-id only). |
| `--create-columns ` | No | Columns to create (--table-id only). |
| `--timezone ` | No | Timezone for date parsing, e.g. America/New\_York. |
| `--no-wait` | No | Return once the import is queued instead of watching it. |
### sim tables ls [#sim-tables-ls]
List table resources and child folders together
```bash
sim tables ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
### sim tables mkdir [#sim-tables-mkdir]
Create a table directory at a path
```bash
sim tables mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim workflows [#sim-workflows]
Also spelled `sim workflow`.
### sim workflows runs cancel [#sim-workflows-runs-cancel]
Cancel a running workflow run
```bash
sim workflows runs cancel [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | ------------ |
| `--workflow ` | Yes | Workflow ID. |
### sim workflows runs get [#sim-workflows-runs-get]
Show run status (requested outputs are included in JSON or YAML output)
```bash
sim workflows runs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | Yes | Workflow ID. |
| `--include-output` | No | Include the final output in JSON or YAML output. |
| `--select-output ` | No | Include blockName.field values in JSON or YAML output (e.g. agent\_1.content) (space-separated, or @path / @- with one value per line). |
### sim workflows runs list [#sim-workflows-runs-list]
List runs for a workflow
```bash
sim workflows runs list [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | Yes | Workflow ID. |
| `--status ` | No | Filter by run status. Accepted values: `pending`, `running`, `completed`, `failed`, `cancelled`, `paused`. |
| `--trigger ` | No | Filter by trigger type. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--order ` | No | Sort direction by run start time. This list is sortable only by run start time, so it takes `order` in place of `sortBy`/`sortOrder`, which it rejects. Accepted values: `asc`, `desc`. |
### sim workflows runs resume [#sim-workflows-runs-resume]
Resume a paused run (output is included in JSON or YAML output)
```bash
sim workflows runs resume [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | ------------------------------------------------------------------- |
| `--workflow ` | Yes | Workflow ID. |
| `--context ` | Yes | Pause context ID returned by run status. |
| `--input ` | No | Resume input as JSON (JSON, or @path / @- to read a file or stdin). |
### sim workflows create [#sim-workflows-create]
Create Workflow
```bash
sim workflows create [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | --------------------------------------- |
| `--name ` | Yes | Workflow name. |
| `--description ` | No | Optional workflow description. |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim workflows folders create [#sim-workflows-folders-create]
Create a workflow folder at a path
```bash
sim workflows folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
### sim workflows folders delete [#sim-workflows-folders-delete]
Delete Workflow Folder
```bash
sim workflows folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
### sim workflows folders list [#sim-workflows-folders-list]
List Workflow Folders
```bash
sim workflows folders list [options]
```
Also available as `sim workflows folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim workflows folders move [#sim-workflows-folders-move]
Rename or move a workflow folder
```bash
sim workflows folders move
```
Also available as `sim workflows folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
### sim workflows delete [#sim-workflows-delete]
Delete Workflow
```bash
sim workflows delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
### sim workflows deploy [#sim-workflows-deploy]
Deploy Workflow
```bash
sim workflows deploy [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------- |
| `--name ` | No | Optional label for the deployment version. |
| `--description ` | No | Optional release note for the deployment version. |
### sim workflows run [#sim-workflows-run]
Run a deployed workflow
```bash
sim workflows run [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--input ` | No | Trigger input as JSON (JSON, or @path / @- to read a file or stdin). |
| `--async` | No | Queue the run and return immediately. |
| `--execution-timeout-seconds ` | No | Requested server-side timeout for an asynchronous run, in seconds. An upper bound, not the effective timeout: the run uses the smaller of this value and the plan's execution timeout, so requesting more than the plan allows silently yields the plan timeout. Rejected with `400` unless `async` is true. |
| `--select-output ` | No | Return blockName.field values (e.g. agent\_1.content); missing fields are omitted (space-separated, or @path / @- with one value per line). |
| `--include-file-base64` | No | Inline eligible output files as base64 content. Rejected when `async` is true. |
| `--no-include-file-base64` | No | Send --include-file-base64 as false. |
| `--base64-max-bytes ` | No | Maximum total bytes of file content to inline as base64. Rejected when `async` is true. |
### sim workflows export [#sim-workflows-export]
Print a workflow as a portable JSON document
```bash
sim workflows export
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
### sim workflows get [#sim-workflows-get]
Get Workflow
```bash
sim workflows get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
### sim workflows deployment list [#sim-workflows-deployment-list]
Get Workflow Deployment
```bash
sim workflows deployment list
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
### sim workflows versions get [#sim-workflows-versions-get]
Get Workflow Version
```bash
sim workflows versions get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
| `version` | Yes | Numeric deployment version. |
### sim workflows versions list [#sim-workflows-versions-list]
List Workflow Versions
```bash
sim workflows versions list [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
### sim workflows import [#sim-workflows-import]
Import Workflow
```bash
sim workflows import [options]
```
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | Yes | Workflow export object, bare workflow state, or JSON string containing either form. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--name ` | No | Override for the imported workflow name. |
| `--description ` | No | Override for the imported workflow description. |
### sim workflows list [#sim-workflows-list]
List Workflows
```bash
sim workflows list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--folder ` | No | Folder path; the leading / is optional. |
| `--deployed-only` | No | Return only workflows with an active deployment when true. |
| `--no-deployed-only` | No | Send --deployed-only as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `position`, `name`, `createdAt`, `updatedAt`, `runCount`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim workflows rollback [#sim-workflows-rollback]
Rollback Workflow
```bash
sim workflows rollback [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | ----------------------------------------------------------------------------- |
| `--version ` | No | Deployment version to reactivate. Omit to select the previous active version. |
### sim workflows undeploy [#sim-workflows-undeploy]
Take a workflow out of deployment
```bash
sim workflows undeploy
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
### sim workflows update [#sim-workflows-update]
Update Workflow
```bash
sim workflows update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------- |
| `id` | Yes | Unique workflow identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------- |
| `--name ` | No | Replacement workflow name. |
| `--description ` | No | Replacement workflow description; null clears it. |
| `--folder ` | No | Folder path; the leading / is optional. |
### sim workflows mv [#sim-workflows-mv]
Move a workflow to a folder
```bash
sim workflows mv
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `id` | Yes | Unique workflow identifier. |
| `folder` | Yes | Folder path; the leading / is optional |
### sim workflows ls [#sim-workflows-ls]
List workflow resources and child folders together
```bash
sim workflows ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `100`. |
### sim workflows mkdir [#sim-workflows-mkdir]
Create a workflow directory at a path
```bash
sim workflows mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim workspaces [#sim-workspaces]
Also spelled `sim workspace`.
### sim workspaces get [#sim-workspaces-get]
Get Workspace
```bash
sim workspaces get
```
### sim workspaces members [#sim-workspaces-members]
List workspace members
```bash
sim workspaces members [options]
```
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
---
# Scripting (/cli/scripting)
Everything below applies to every command.
## Reading input from files and stdin [#reading-input-from-files-and-stdin]
Any flag that takes JSON or a list also accepts `@path` to read a file, or `@-`
to read stdin.
```bash
sim workflows import --workflow @wf.json
sim tables rows query tbl_123 --filter @filter.json
cat wf.json | sim workflows import --workflow @-
```
## List flags [#list-flags]
Primitive lists take space-separated values. With `@`, the file supplies one
value per line:
```bash
sim files mv --file-ids file_1 file_2 --to Archive
sim files mv --file-ids @file-ids.txt --to Archive
printf 'file_1\nfile_2\n' | sim files mv --file-ids @- --to Archive
```
Arrays of objects stay JSON.
## Filtering table rows [#filtering-table-rows]
`--filter` takes the same predicate tree the API uses: `all` (AND) or `any` (OR)
groups of `{field, op, value}` conditions, nestable.
```bash
sim tables rows query tbl_123 \
--filter '{"all":[{"field":"status","op":"eq","value":"open"},
{"field":"score","op":"gt","value":10}]}' \
--limit 50
```
Operators: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`, `contains`,
`ncontains`, `startsWith`, `endsWith`, `like`, `ilike`, `nlike`, `nilike`,
`isEmpty`, `isNotEmpty`, `isNull`, `isNotNull`.
`--sort` is also JSON, an ordered list of keys:
```bash
sim tables rows query tbl_123 --sort '[{"field":"createdAt","direction":"desc"}]'
```
## Pagination [#pagination]
List commands page automatically up to `--limit`, which defaults to `100`. Pass
`--limit 0` to fetch everything:
```bash
sim logs list --limit 0 --output json > all-logs.json
```
## Destructive commands [#destructive-commands]
Deletions require an explicit selector **and** `--yes`. There is no "delete
everything" default:
```bash
sim tables rows batch-delete tbl_123 --row row_1 row_2 --yes
sim files delete file_123 --yes
```
Without `--yes` the command explains what it would have destroyed and stops.
`batch-delete` and `batch-update` carry the default `--limit` of `100`, so a
filter matching more rows than that silently affects only the first 100. Pass
`--limit 0` to affect every matching row.
## Exit codes [#exit-codes]
| Code | Meaning |
| ---- | ------------------------------------------------------------------------------------- |
| `0` | Success |
| `1` | Anything else — API error, bad configuration, invalid arguments, or a missing `--yes` |
Errors print one line to stderr, prefixed `Error:`, plus the API's error code and
validation details when it supplies them. Failures are safe to branch on:
```bash
if ! sim workflows run wf_7Yb2 --output json > result.json; then
echo "run failed" >&2
exit 1
fi
```
An unexpected error prints a stack trace — that is a bug in the CLI, so please
[open an issue](https://github.com/simstudioai/sim/issues).
## Selecting workflow output [#selecting-workflow-output]
`--select-output` takes `blockName.field` selectors. Fields that a run did not
produce are simply omitted:
```bash
sim workflows run wf_7Yb2 --select-output agent_1.content --output json
```
## Polling a long run [#polling-a-long-run]
Start the run asynchronously, then poll its status:
```bash
run_id=$(sim workflows run wf_7Yb2 --async --output json | jq -r '.runId')
until sim workflows runs get "$run_id" --workflow wf_7Yb2 --output json \
| jq -e '.status | IN("completed","failed","cancelled")' > /dev/null; do
sleep 5
done
sim logs get "$run_id" --trace
```
`workflows runs get` is the lightweight status check; `logs get` is the full
diagnostic. For a paused run, the status includes the context ID that
`sim workflows runs resume` needs.
## Working with folders [#working-with-folders]
Every folder-backed resource — `workflows`, `tables`, `files`, `knowledge` —
shares the same path commands:
```bash
sim tables ls Reports
sim tables mkdir Reports/Quarterly
sim tables folders mv Reports/Quarterly Archive/Quarterly
sim tables folders delete Archive --recursive --yes
```
`ls` lists the resources at a path plus that folder's direct children, never
deeper. Its `ref` column is the value to pass to the next command. Use `list` for
resources only, or `folders ls` for folders only. A leading `/` is optional.
## A nightly job, end to end [#a-nightly-job-end-to-end]
```bash title="nightly-digest.sh"
#!/usr/bin/env bash
set -euo pipefail
export SIM_API_KEY="${SIM_API_KEY:?missing}"
export SIM_WORKSPACE="${SIM_WORKSPACE:?missing}"
export SIM_OUTPUT=json
run_id=$(sim workflows run wf_7Yb2 --input '{"source":"nightly"}' | jq -r '.runId')
if [ "$(sim workflows runs get "$run_id" --workflow wf_7Yb2 | jq -r '.status')" != "completed" ]; then
sim logs get "$run_id" >&2
exit 1
fi
```
---
# Secrets (/cli/secrets)
`sim secrets` is also spelled `sim secret`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Delete secret [#delete-secret]
```bash
sim secrets delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------- |
| `name` | Yes | Secret to create, replace, or delete. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | Yes | Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace. Accepted values: `workspace`, `personal`. |
| `-y, --yes` | No | Skip the confirmation. |
## List secrets [#list-secrets]
```bash
sim secrets list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Restrict results to one ownership scope. Accepted values: `workspace`, `personal`. |
| `--search ` | No | Case-insensitive substring match against the secret name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## Create or replace a named secret [#create-or-replace-a-named-secret]
```bash
sim secrets set [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | --------------------------------------- |
| `name` | Yes | Secret name, as referenced in workflows |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ----------------------------------------------------------------- |
| `--scope ` | Yes | Secret ownership scope. Accepted values: `workspace`, `personal`. |
| `--value ` | No | Secret value; visible to shell history when supplied directly. |
---
# Skills (/cli/skills)
`sim skills` is also spelled `sim skill`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Create skill [#create-skill]
```bash
sim skills create [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--name ` | Yes | Kebab-case name, unique within the workspace and not reserved by a built-in skill. |
| `--description ` | Yes | One-line summary of when the skill applies. |
| `--content ` | Yes | Skill body containing the instructions given to the agent. |
## Delete skill [#delete-skill]
```bash
sim skills delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Get skill [#get-skill]
```bash
sim skills get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
## List skills [#list-skills]
```bash
sim skills list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the skill name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
## Update skill [#update-skill]
```bash
sim skills update [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ----------------------------------------------- |
| `--name ` | No | New kebab-case skill name. |
| `--description ` | No | New one-line summary of when the skill applies. |
| `--content ` | No | Replacement skill body. |
---
# Tables (/cli/tables)
`sim tables` is also spelled `sim table`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Add column [#add-column]
```bash
sim tables columns create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ------------------------------------------------------------------------ |
| `--column ` | Yes | Column definition to add. (JSON, or @path / @- to read a file or stdin). |
## Delete column [#delete-column]
```bash
sim tables columns delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ----------------------------- |
| `--column-name ` | Yes | Name of the column to delete. |
| `-y, --yes` | No | Skip the confirmation. |
## Run a column’s workflow [#run-a-columns-workflow]
```bash
sim tables columns run [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--group-ids ` | Yes | Workflow or enrichment groups to run. (space-separated, or @path / @- with one value per line). |
| `--run-mode ` | No | Whether to run all or only incomplete cells. Accepted values: `all`, `incomplete`. |
| `--row-ids ` | No | Explicit row subset to run. (space-separated, or @path / @- with one value per line). |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--exclude-row-ids ` | No | Rows excluded from a select-all run scope. (space-separated, or @path / @- with one value per line). |
| `--limit ` | No | Optional cap on eligible rows to run. (JSON, or @path / @- to read a file or stdin). |
## Update column [#update-column]
```bash
sim tables columns update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------- |
| `--column-name ` | Yes | Current name of the column to update. |
| `--updates ` | Yes | Mutable column fields. (JSON, or @path / @- to read a file or stdin). |
## Add workflow group [#add-workflow-group]
```bash
sim tables groups create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `--group ` | Yes | Workflow or enrichment producer definition. (JSON, or @path / @- to read a file or stdin). |
| `--output-columns ` | Yes | Columns created for producer outputs. (JSON, or @path / @- to read a file or stdin). |
| `--auto-run` | No | Whether to schedule existing rows after group creation. |
| `--no-auto-run` | No | Send --auto-run as false. |
## Delete workflow group [#delete-workflow-group]
```bash
sim tables groups delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------- |
| `--group-id ` | Yes | Workflow group to delete. |
| `-y, --yes` | No | Skip the confirmation. |
## List workflow groups [#list-workflow-groups]
```bash
sim tables groups list
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
## Update workflow group [#update-workflow-group]
```bash
sim tables groups update [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--group-id ` | Yes | Workflow group to update. |
| `--workflow-id ` | No | Replacement backing workflow identifier. |
| `--name ` | No | Replacement workflow-group display name. |
| `--dependencies ` | No | Replacement input dependencies. (JSON, or @path / @- to read a file or stdin). |
| `--outputs ` | No | Replacement producer outputs. (JSON, or @path / @- to read a file or stdin). |
| `--new-output-columns ` | No | Columns to add for new outputs. (JSON, or @path / @- to read a file or stdin). |
| `--mapping-updates ` | No | Existing output-column mapping changes. (JSON, or @path / @- to read a file or stdin). |
| `--input-mappings ` | No | Replacement workflow input mappings. (JSON, or @path / @- to read a file or stdin). |
| `--deployment-mode ` | No | Replacement workflow execution mode. Accepted values: `live`, `deployed`. |
| `--type ` | No | Workflow-group producer type. Must match the group's stored type — a group's producer cannot be changed after creation. Accepted values: `manual`, `enrichment`. |
| `--auto-run` | No | Replacement automatic-run setting. |
| `--no-auto-run` | No | Send --auto-run as false. |
## Cancel table export [#cancel-table-export]
```bash
sim tables exports cancel
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
## Create table export [#create-table-export]
```bash
sim tables exports create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------ | -------- | --------------------------------------------------- |
| `--format ` | No | Export file format. Accepted values: `csv`, `json`. |
## Get table export [#get-table-export]
```bash
sim tables exports get
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
## Get the download URL for a finished export [#get-the-download-url-for-a-finished-export]
```bash
sim tables exports download
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `exportId` | Yes | Unique table-export identifier. |
## Cancel table import [#cancel-table-import]
```bash
sim tables imports cancel
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `importId` | Yes | Unique table-import identifier. |
## Get table import [#get-table-import]
```bash
sim tables imports get
```
**Arguments**
| Argument | Required | Description |
| ---------- | -------- | ------------------------------- |
| `importId` | Yes | Unique table-import identifier. |
## Stop every running column job [#stop-every-running-column-job]
```bash
sim tables cancel-runs [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | Yes | Whether to cancel across the table or one row. Accepted values: `all`, `row`. |
| `--row-id ` | No | Row whose runs should be canceled for row scope. |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--exclude-row-ids ` | No | Rows excluded from an all-scope cancellation. (space-separated, or @path / @- with one value per line). |
## Create table [#create-table]
```bash
sim tables create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Identifier: letters, numbers, and underscores; cannot start with a number. |
| `--description ` | No | Optional table description. |
| `--schema ` | Yes | Table schema: \{"columns":\[\{"name":"email","type":"string"}]} (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path; the leading / is optional. |
## Create a table folder at a path [#create-a-table-folder-at-a-path]
```bash
sim tables folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
## Delete folder [#delete-folder]
```bash
sim tables folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | No | Skip the confirmation. |
## List folders [#list-folders]
```bash
sim tables folders list [options]
```
Also available as `sim tables folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
## Rename or move a table folder [#rename-or-move-a-table-folder]
```bash
sim tables folders move
```
Also available as `sim tables folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `path` | Yes | Folder path; the leading / is optional |
| `destination` | Yes | Folder path; the leading / is optional |
## Create rows [#create-rows]
```bash
sim tables rows create [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------- |
| `--data ` | No | One row keyed by column name (JSON, or @path / @-; choose exactly one body flag). |
| `--rows ` | No | Several rows keyed by column name (JSON, or @path / @-; choose exactly one body flag). |
## Delete row [#delete-row]
```bash
sim tables rows delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ---------------------------- |
| `tableId` | Yes | Unique table identifier. |
| `rowId` | Yes | Unique table row identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ---------------------- |
| `-y, --yes` | No | Skip the confirmation. |
## Delete rows matching a filter, or an explicit list of ids [#delete-rows-matching-a-filter-or-an-explicit-list-of-ids]
```bash
sim tables rows batch-delete [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------ |
| `tableId` | Yes | Unique table identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filter ` | No | Predicate: \{"all":\[\{"field":"status","op":"eq","value":"active"}]}; groups use all/any. Operators: eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, isNotNull (JSON, or @path / @- to read a file or stdin). |
| `--limit