> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guild.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> To act on a user's behalf in Guild, use the Guild REST API at https://api.guild.ai/v1.
> The OpenAPI spec is unauthenticated: https://docs.guild.ai/openapi.json (or openapi.yaml).
> Authenticate with an account API key, sent as HTTP Basic (key id as username, secret as password) or as `Authorization: Bearer <api_key_id>:<api_key_secret>`. See https://docs.guild.ai/api-reference/introduction#authentication.
> To run one agent on demand without account-wide access, use an API trigger instead: https://docs.guild.ai/platform/api-triggers.
> To act on Guild from an MCP client, connect to https://api.guild.ai/mcp (OAuth) or run `guild mcp` locally. Setup: https://docs.guild.ai/api-reference/mcp.
> To search these docs from an MCP client, connect to https://docs.guild.ai/mcp. The full page index is https://docs.guild.ai/llms.txt.

# Migrate from CrewAI to Guild

> Rewrite CrewAI crews and flows as Guild Native or TypeScript agents, and map tasks, tools, delegation, human input, and AMP triggers to Guild.

CrewAI is an MIT-licensed Python framework (`crewai`, 1.15 as of November 2026) for role-based agent **crews** and event-driven **flows**. A crew is a set of agents, each with a role, a goal, and a backstory, working through tasks in a sequential or hierarchical process. A flow wires crews and plain code together with `@start`, `@listen`, and `@router`. CrewAI AMP deploys crews and gives them a REST API, app triggers, and traces.

Guild doesn't run CrewAI code. A crew moves to Guild by rewriting it: crews that are only prompts become Native agents, and crews with several steps, typed output, or flows become TypeScript agents.

## Who this is for

Teams with CrewAI crews or flows, run locally, on their own servers, or on CrewAI AMP, who want them in a shared workspace. On Guild, credentials stay behind a proxy, admins set ALLOW/DENY policies on each operation, and every run shows in one place.

## Concept map

| CrewAI | Guild |
| - | - |
| Agent `role`, `goal`, and `backstory` (`agents.yaml` or `agents/<name>.jsonc`) | Instructions: `PROMPT.md` in a Native agent, or the `system` prompt of each step in a TypeScript agent |
| `Agent(llm=...)`, `MODEL=provider/model` | The `models` fallback list in `guild.yaml`, or account LLM settings for TypeScript agents |
| `Task` (`description`, `expected_output`) in `tasks.yaml` | One [`task.llm.generateText`](https://docs.guild.ai/guide/llms) call in `run()` for each task |
| `Task(output_pydantic=...)` or `output_json` | A zod `schema` on that `generateText` call, or the agent's `outputSchema` for the final task |
| `Task(context=[...])` | Passing the earlier step's result into the next step's prompt |
| `{placeholder}` inputs filled by `kickoff(inputs=...)` | Fields on the agent's `inputSchema` |
| `Crew(process=Process.sequential)` | A TypeScript `run()` that calls each step in order |
| `Process.hierarchical`, `allow_delegation=True` | A lead agent that calls specialist Guild agents with `guildAgentTool` |
| `async_execution=True`, `kickoff_for_each` | Parallel calls with [`task.gather`](https://docs.guild.ai/guide/tasks) in `run()` |
| Flow `@start`, `@listen`, `@router` | Functions called from `run()`, with `if` or `switch` for routers |
| `crewai_tools`, custom tools that call an API, `apps=[...]` | The catalog [integration](https://docs.guild.ai/integrations/overview.md) for the service, or a [custom integration](https://docs.guild.ai/services/create-an-integration.md) from its OpenAPI spec |
| Custom `BaseTool` or `@tool` that only computes | A function in `logic.ts` |
| `mcps=[...]`, `MCPServerAdapter` | The catalog integration for the same service, or a [custom MCP integration](https://docs.guild.ai/services/create-an-integration.md) created from the server's URL in the web app |
| `.env`, AMP environment variables, Secrets Manager | [Credentials](https://docs.guild.ai/platform/credentials.md) for secrets, and [workspace variables](https://docs.guild.ai/platform/workspace-variables.md) for settings |
| `user_bearer_token` at kickoff | Member-scoped credentials, plus [identity mapping](https://docs.guild.ai/platform/identity-mapping.md) |
| `Task(human_input=True)`, Flow `@human_feedback` | A `ui_prompt` in `run()`; the run pauses until someone answers |
| AMP triggers (Gmail, Slack, Salesforce) and `crewai_trigger_payload` | An [event trigger](https://docs.guild.ai/platform/event-triggers.md) on the matching integration; the event arrives in the input as `{webhook_payload}` |
| AMP `POST /kickoff` | An [API trigger](https://docs.guild.ai/platform/api-triggers.md), or `guild workspace chat --once` |
| CrewAI skills (`crewai skill publish`) | `skills/<name>/SKILL.md` in an OpenClaw agent (same format), or a [Guild skill](https://docs.guild.ai/platform/skills.md) |
| `crewai test`, `crewai train`, `crewai eval` | [Guild Evaluations](https://docs.guild.ai/platform/evaluations.md) and `guild agent test` |
| AMP traces and the Agent Control Plane | The session event log, Insights, and Spend Explorer |
| `crewai deploy create`, `crewai deploy push` | `guild agent save --wait --publish` |

## Before you start

```bash theme={null}
guild auth login
guild workspace select
```

## Inventory

CrewAI projects come in three shapes. Most existing repositories use the classic one: `crew.py` with `@CrewBase`, plus `config/agents.yaml` and `config/tasks.yaml`. Newer projects from `crewai create crew` put `crew.jsonc` and `agents/<name>.jsonc` at the root. Declarative flows use a `flow.yaml`.

List these before writing any Guild code. Record names only, never secret values.

* Every agent's role, goal, and backstory, and every task's description and expected output.
* Each `{placeholder}` in those files. They're filled from `kickoff(inputs=...)` and become fields on the Guild agent's input.
* The process (sequential or hierarchical), and which agents set `allow_delegation=True`.
* For flows, each `@start`, `@listen`, and `@router` method and the state it reads or writes.
* Every tool: `crewai_tools` imports, custom `BaseTool` or `@tool` code and what it calls, `apps=[...]`, and `mcps=[...]` or `MCPServerAdapter` servers.
* Tasks with `human_input=True`, `output_pydantic`, `output_json`, `guardrail`, or `output_file`.
* Memory, knowledge sources under `knowledge/`, and `@persist` or checkpoint settings.
* AMP triggers turned on for the deployment, and environment variables, by name only.

## Steps

> [tab] Crew of prompts → Native
>
> Use this path when the crew's tasks are prompts that pass text along and its tools come from integrations.
>
> **1. Scaffold a Native agent**
>
> ```bash theme={null}
> guild agent init --name inbox-brief --agent-type GUILD_NATIVE \
>   --category <category> --owner <owner>
> ```
>
> `--category` and `--owner` stop the CLI from prompting, which a script or coding agent can't answer. List categories with `guild agent categories`.
>
> **2. Fold the roles and tasks into PROMPT.md**
>
> Write one set of instructions that covers each agent's role and goal and each task in order. Replace every `{placeholder}` with a sentence that tells the agent what to ask for or expect in the request.
>
> ```markdown PROMPT.md theme={null}
> You write a short morning brief from the user's inbox.
>
> 1. Find unread emails from the last 24 hours.
> 2. Group them by sender and pick the five that need a reply.
> 3. Write a brief with a one-line summary for each.
>
> Before you send anything, confirm with the user using ui_prompt.
> ```
>
> **3. Declare the tools in guild.yaml**
>
> Each `apps=[...]` entry or `crewai_tools` tool becomes a Guild integration with only the operations the agent calls:
>
> ```yaml guild.yaml theme={null}
> integrations:
>   - name: <owner>~gmail
>     version: ^1.0.0
>     tools: [gmail_messages_list, gmail_messages_get]
> builtins:
>   - name: ui
>     tools: [ui_prompt]
> ```
>
> Check the real names with `guild integration list` and `guild integration operation list <owner~integration> --json`. The ones above are illustrative.
>
> **4. Test**
>
> ```bash theme={null}
> git add -A
> guild agent test
> ```
>
> `guild agent test` collects files by walking your local directory and honoring `.gitignore`, the same way `guild agent save` does, so new files such as `logic.ts` are uploaded even without `git add`.

> [tab] Sequential crew or flow → TypeScript
>
> Use this path when the crew has several tasks in a fixed order, typed task output, `{placeholder}` inputs, or a flow.
>
> **1. Scaffold a TypeScript agent**
>
> ```bash theme={null}
> guild agent init --name exec-brief --agent-type GUILD_TYPESCRIPT --template LLM \
>   --category <category> --owner <owner>
> ```
>
> `--category` and `--owner` stop the CLI from prompting, which a script or coding agent can't answer. List categories with `guild agent categories`.
>
> **2. Port tasks to steps**
>
> Each task becomes a model call in `run()`, each agent's role becomes that call's `system`, and each `{placeholder}` becomes an input field. `human_input=True` becomes a `ui_prompt` before the result returns.
>
> ```ts Guild: agent.ts theme={null}
> "use agent";
> import { agent, pick, userInterfaceTools, type Task } from "@guildai/agents-sdk";
> import { z } from "zod";
>
> const inputSchema = z.object({ topic: z.string().max(200) });
> const outputSchema = z.object({ title: z.string(), summary: z.string(), risks: z.array(z.string()).max(3) });
> const tools = { ...pick(userInterfaceTools, ["ui_prompt"]) };
>
> async function run(input: z.infer<typeof inputSchema>, task: Task<typeof tools>) {
>   const research = await task.llm.generateText({
>     system: "You are a senior data researcher.",
>     prompt: `Research the latest developments in ${input.topic}. Return ten bullet points.`,
>   });
>   const brief = await task.llm.generateText({
>     system: "You are an executive writer. Write briefs that are short and concrete.",
>     prompt: `Turn this research into a brief with a title, a summary, and three risks:\n\n${research.text}`,
>     schema: outputSchema,
>   });
>   const answer = await task.tools.ui_prompt({
>     type: "text",
>     text: `Draft brief:\n\n${brief.title}\n\n${brief.summary}\n\nReply "ok" to accept.`,
>   });
>   if (!/^\s*ok\b/i.test(answer.text)) throw new Error("Brief not accepted");
>   return brief;
> }
>
> export default agent({ description: "Researches a topic and writes an executive brief, with a human review.", inputSchema, outputSchema, tools, run });
> ```
>
> ```yaml CrewAI: config/tasks.yaml theme={null}
> research_task:
>   description: Research the latest developments in {topic}.
>   expected_output: Ten bullet points about {topic}.
>   agent: researcher
> brief_task:
>   description: Turn the research into a one-page brief for executives.
>   expected_output: A brief with a title, a summary, and three risks.
>   agent: writer
>   human_input: true
> ```
>
> ```python CrewAI: crew.py theme={null}
> class Brief(BaseModel):
>     title: str
>     summary: str
>     risks: list[str]
>
> @CrewBase
> class BriefCrew():
>     @task
>     def brief_task(self) -> Task:
>         return Task(config=self.tasks_config["brief_task"], output_pydantic=Brief)
>
>     @crew
>     def crew(self) -> Crew:
>         return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential)
> ```
>
> For a flow, each `@start` and `@listen` method becomes a function that `run()` calls, and each `@router` becomes an `if` or `switch`. Parallel tasks become an inline [`task.gather([...])`](https://docs.guild.ai/guide/tasks).
>
> **3. Turn delegation into sub-agents**
>
> For a hierarchical crew or `allow_delegation=True`, publish each specialist as its own Guild agent. Call it from the lead agent with `guildAgentTool({ calls: "owner~agent", inputSchema, outputSchema })`.
>
> **4. Replace tools with integrations**
>
> The Guild runtime has no general network egress, so each tool that calls an API becomes an integration operation registered with `pick(...)`. Tools that only compute move to `logic.ts`.
>
> ```bash theme={null}
> guild integration list
> guild integration operation list <owner~integration> --json
> ```
>
> For an MCP server with no catalog integration, create one from the server's URL in the web app. Choose the **MCP** protocol in [Create an integration](https://docs.guild.ai/services/create-an-integration.md).
>
> **5. Test**
>
> ```bash theme={null}
> pnpm install && pnpm test
> git add -A
> guild agent test
> ```
>
> The scaffold has no `test` script, so `pnpm test` passes without running anything. Add a `test` script to `package.json` before you rely on it, such as `"test": "tsc --build && node --test logic.test.mjs"`. If `pnpm install` fails with `ERR_PNPM_IGNORED_BUILDS`, newer pnpm is blocking esbuild's install script. Run `pnpm approve-builds`, approve esbuild, and install again.
>
> `guild agent test` collects files by walking your local directory and honoring `.gitignore`, the same way `guild agent save` does, so new files such as `logic.ts` are uploaded even without `git add`.
>
> Send the same inputs the crew handled and compare the results.

Then publish and wire triggers. An AMP Gmail or Slack trigger becomes an event trigger on the matching integration, and the event arrives in the input text:

```bash theme={null}
guild agent save --message "Port from CrewAI" --wait --publish
guild workspace agent add <owner~agent> --workspace <owner~workspace>
guild trigger create --workspace <owner~workspace> --type webhook --agent <owner~agent> \
  --integration slack --event app_mention \
  --input '{"type":"text","text":"{webhook_payload}"}'
```

> [!NOTE]
>
> The first `guild agent save --wait --publish` after `guild agent init` fails with "No saved state… use --force" because of the `.gitignore` the scaffold writes. Add `--force` to that first save for now.

You can also publish with the [Publish Agent to Guild](https://docs.guild.ai/migrations/overview.md#publish-from-github-actions) GitHub Action instead of `guild agent save --publish`. The Action needs an account API key with the `agents:write` scope:

```bash theme={null}
guild api-key create --owner <owner> --name "Publish migrated agent" --scopes agents:write
```

## Credentials and policies

Remove model provider keys from `.env`; Guild routes model calls through its own proxy. Recreate each tool's API key or AMP integration connection as a Guild [credential](https://docs.guild.ai/platform/credentials.md). Use member scope where the crew relied on `user_bearer_token`, so each person's runs use their own account. Non-secret settings become [workspace variables](https://docs.guild.ai/platform/workspace-variables.md).

Guild splits a tool approval into two controls:

* **Who can call it.** Add a [credential policy](https://docs.guild.ai/platform/credential-policies.md) rule scoped to the agent and workspace that allows or denies the operation. DENY wins over ALLOW.
* **Sign-off on each call.** Add the `ui_prompt` built-in and have the agent confirm with the user before it calls the tool. The run pauses until someone answers.

## What doesn't map 1:1

> [accordion] Hierarchical crews
>
> A hierarchical crew's manager delegates through tools CrewAI injects ("Delegate work to coworker" and "Ask question to coworker"). Guild has no automatic manager. Write each delegation as a call to a specialist Guild agent with `guildAgentTool`, from a lead agent that decides which specialist to call.

> [accordion] Crew Studio
>
> Crew Studio's visual canvas has no Guild equivalent. Guild agents are instructions or code.

> [accordion] Self-hosting
>
> The CrewAI framework runs anywhere under MIT, and AMP can be self-hosted as CrewAI Factory. Guild is a hosted platform, so self-hosted crews move to Guild's runtime.

> [accordion] Memory, knowledge, and saved state
>
> CrewAI memory (LanceDB under `./.crewai/memory`), knowledge sources with embeddings, `@persist` flow state, and checkpoints all live on disk. Guild agents don't keep files between runs and have no vector memory. Put short reference text in the instructions or an OpenClaw skill, and keep durable state in an outside store reached through an integration.

> [accordion] Tool hooks, callbacks, and planning
>
> Tool hooks (`@before_tool_call`, `@after_tool_call`), `step_callback`, `task_callback`, and `planning=True` have no direct equivalent. Use [credential policies](https://docs.guild.ai/platform/credential-policies.md) to limit which operations the agent can call, and write checks as code in `run()`.

> [accordion] Human input
>
> `human_input=True` blocks on a console prompt locally and pauses with `/resume` on AMP. On Guild, the agent asks with `ui_prompt` and the run pauses until someone answers in the session. A run started by a schedule or webhook waits the same way.

> [accordion] Test and training runs
>
> `crewai test`, `crewai train`, and `crewai eval` don't run on Guild. Rebuild the important cases as Guild Evaluations or `guild agent test` sessions. If the repository has a `trained_agents_data.pkl`, fold its useful suggestions into the instructions.

> [accordion] Local MCP servers
>
> Guild connects to remote MCP servers by URL. A local stdio server, such as an `MCPServerStdio` that runs `npx`, needs a hosted HTTP endpoint first. Otherwise, move its tools to an integration built from the service's OpenAPI spec.

## Three ways to migrate

> [card] [guild-migrate skill](https://docs.guild.ai/migrations/guild-migrate-skill.md)
>
> Ask your coding agent: "Migrate this CrewAI crew to Guild." It picks Native or TypeScript and writes `MIGRATION.md`.

> [card] [Publish Agent to Guild Action](https://docs.guild.ai/migrations/overview.md#publish-from-github-actions)
>
> Commit the port to your repository, then publish it from GitHub Actions with an account API key.

> [card] [Migration agent](https://app.guild.ai/organizations/guildai/agents/guildai~migrate-to-guild)
>
> Point Migrate to Guild at your repository; it opens a draft pull request. The guild-migrate skill ships in the same package.

## Related pages

> [card] [TypeScript agents](https://docs.guild.ai/guide/coded-agents.md)
>
> `agent()`, `run`, typed input and output, and the task object.

> [card] [LLM calls](https://docs.guild.ai/guide/llms.md)
>
> `task.llm.generateText` with structured output.

Migrating a team? [Talk to us](https://www.guild.ai/talk-to-sales?utm_source=docs\&utm_medium=referral\&utm_campaign=migrations).
