Compare commits

...

6 Commits

Author SHA1 Message Date
Devin AI
c001517b48 ci: retrigger test matrix after type-check fix
Co-Authored-By: João <joao@crewai.com>
2026-04-21 06:11:11 +00:00
Devin AI
a556f261a3 fix(integrations/signet): use importlib.import_module for lazy signet_auth import
Avoids mypy 'unused type: ignore' error on Python 3.10 and 3.13 when
signet_auth isn't installed in the type-check environment.

Co-Authored-By: João <joao@crewai.com>
2026-04-21 06:01:29 +00:00
Devin AI
53c6ae4c5e feat(integrations): add optional Signet integration
Adds an opt-in `crewai.integrations.signet` module that produces
Ed25519-signed Signet receipts for every governed action emitted on
the CrewAI event bus: structured tool calls, MCP tool executions,
and A2A delegations.

- Lazy-imports `signet-auth` with a clear ImportError if the
  `crewai[signet]` extra is not installed.
- Pairs started/completed events via `started_event_id` so each
  receipt covers both the input and the output of a single action.
- Adds configuration surfaces (audit log, policy attestation,
  per-surface toggles) via `SignetConfig`.
- Ships tests covering all three event surfaces with a mocked
  SigningAgent.

Closes #5568

Co-Authored-By: João <joao@crewai.com>
2026-04-21 05:56:27 +00:00
iris-clawd
3b01da9ad9 docs: add Build with AI to Get Started nav + page files for all languages (en, ko, pt-BR, ar) (#5567)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-04-20 23:43:37 -03:00
iris-clawd
874405b825 docs: Add 'Build with AI' page — AI-native docs for coding agents (#5558)
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Vulnerability Scan / pip-audit (push) Has been cancelled
Nightly Canary Release / Check for new commits (push) Has been cancelled
Nightly Canary Release / Build nightly packages (push) Has been cancelled
Nightly Canary Release / Publish nightly to PyPI (push) Has been cancelled
* docs: add Build with AI page for coding agents and AI assistants

* docs: add Build with AI section to README

* docs: trim README Build with AI section to skills install only

* docs: add skills.sh reference link for npx install

* docs: add coding agent logos to Build with AI page

---------

Co-authored-by: Lorenze Jay <63378463+lorenzejay@users.noreply.github.com>
2026-04-20 16:09:37 -07:00
Greyson LaLonde
d6d04717c2 fix: serialize Task class-reference fields for checkpointing
Task fields that store class references (output_pydantic, output_json,
response_model, converter_cls) caused PydanticSerializationError when
RuntimeState serialized Crew entities during checkpointing. Serialize
to model_json_schema() and hydrate back via create_model_from_schema.
2026-04-21 03:15:06 +08:00
16 changed files with 1840 additions and 17 deletions

View File

@@ -83,6 +83,7 @@ intelligent automations.
## Table of contents
- [Build with AI](#build-with-ai)
- [Why CrewAI?](#why-crewai)
- [Getting Started](#getting-started)
- [Key Features](#key-features)
@@ -101,6 +102,22 @@ intelligent automations.
- [Telemetry](#telemetry)
- [License](#license)
## Build with AI
Using an AI coding agent? Teach it CrewAI best practices in one command:
**Claude Code:**
```shell
/plugin marketplace add crewAIInc/skills
```
**Cursor, Codex, Windsurf, and others ([skills.sh](https://skills.sh/crewaiinc/skills)):**
```shell
npx skills add crewaiinc/skills
```
This installs the official [CrewAI Skills](https://github.com/crewAIInc/skills) — structured instructions that teach coding agents how to scaffold Flows, configure Crews, design agents and tasks, and follow CrewAI patterns.
## Why CrewAI?
<div align="center" style="margin-bottom: 30px;">

View File

@@ -0,0 +1,206 @@
---
title: "Build with AI"
description: "Everything AI coding agents need to build, deploy, and scale with CrewAI — skills, machine-readable docs, deployment, and enterprise features."
icon: robot
mode: "wide"
---
# Build with AI
CrewAI is AI-native. This page brings together everything an AI coding agent needs to build with CrewAI — whether you're Claude Code, Codex, Cursor, Gemini CLI, or any other assistant helping a developer ship crews and flows.
### Supported Coding Agents
<CardGroup cols={5}>
<Card title="Claude Code" icon="message-bot" color="#D97706" />
<Card title="Cursor" icon="arrow-pointer" color="#3B82F6" />
<Card title="Codex" icon="terminal" color="#10B981" />
<Card title="Windsurf" icon="wind" color="#06B6D4" />
<Card title="Gemini CLI" icon="sparkles" color="#8B5CF6" />
</CardGroup>
<Note>
This page is designed to be consumed by both humans and AI assistants. If you're a coding agent, start with **Skills** to get CrewAI context, then use **llms.txt** for full docs access.
</Note>
---
## 1. Skills — Teach Your Agent CrewAI
**Skills** are instruction packs that give coding agents deep CrewAI knowledge — how to scaffold Flows, configure Crews, use tools, and follow framework conventions.
<Tabs>
<Tab title="Claude Code (Plugin Marketplace)">
<img src="https://cdn.simpleicons.org/anthropic/D97706" alt="Anthropic" width="28" style={{display: "inline", verticalAlign: "middle", marginRight: "8px"}} />
CrewAI skills are available in the **Claude Code plugin marketplace** — the same distribution channel used by top AI-native companies:
```
/plugin marketplace add crewAIInc/skills
```
</Tab>
<Tab title="npx (Any Agent)">
Works with Claude Code, Codex, Cursor, Gemini CLI, or any coding agent:
```shell
npx skills add crewaiinc/skills
```
Pulls from the [skills.sh registry](https://skills.sh/crewaiinc/skills).
</Tab>
</Tabs>
<Steps>
<Step title="Install the official skill pack">
Use either method above — the Claude Code plugin marketplace or `npx skills add`. Both install the official [crewAIInc/skills](https://github.com/crewAIInc/skills) pack.
</Step>
<Step title="Your agent gets instant CrewAI expertise">
The skill pack teaches your agent:
- **Flows** — stateful apps, steps, and crew kickoffs
- **Crews & Agents** — YAML-first patterns, roles, tasks, delegation
- **Tools & Integrations** — search, APIs, MCP servers, and common CrewAI tools
- **Project layout** — CLI scaffolds and repo conventions
- **Up-to-date patterns** — tracks current CrewAI docs and best practices
</Step>
<Step title="Start building">
Your agent can now scaffold and build CrewAI projects without you re-explaining the framework each session.
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Skills concept" icon="bolt" href="/en/concepts/skills">
How skills work in CrewAI agents — injection, activation, and patterns.
</Card>
<Card title="Skills landing page" icon="wand-magic-sparkles" href="/en/skills">
Overview of the crewAIInc/skills pack and what it includes.
</Card>
<Card title="AGENTS.md & coding tools" icon="terminal" href="/en/guides/coding-tools/agents-md">
Set up AGENTS.md for Claude Code, Codex, Cursor, and Gemini CLI.
</Card>
<Card title="Skills registry (skills.sh)" icon="globe" href="https://skills.sh/crewaiinc/skills">
Official listing — skills, install stats, and audits.
</Card>
</CardGroup>
---
## 2. llms.txt — Machine-Readable Docs
CrewAI publishes an `llms.txt` file that gives AI assistants direct access to the full documentation in a machine-readable format.
```
https://docs.crewai.com/llms.txt
```
<Tabs>
<Tab title="What is llms.txt?">
[`llms.txt`](https://llmstxt.org/) is an emerging standard for making documentation consumable by large language models. Instead of scraping HTML, your agent can fetch a single structured text file with all the content it needs.
CrewAI's `llms.txt` is **already live** — your agent can use it right now.
</Tab>
<Tab title="How to use it">
Point your coding agent at the URL when it needs CrewAI reference docs:
```
Fetch https://docs.crewai.com/llms.txt for CrewAI documentation.
```
Many coding agents (Claude Code, Cursor, etc.) can fetch URLs directly. The file contains structured documentation covering all CrewAI concepts, APIs, and guides.
</Tab>
<Tab title="Why it matters">
- **No scraping required** — clean, structured content in one request
- **Always up-to-date** — served directly from docs.crewai.com
- **Optimized for LLMs** — formatted for context windows, not browsers
- **Complements skills** — skills teach patterns, llms.txt provides reference
</Tab>
</Tabs>
---
## 3. Deploy to Enterprise
Go from a local crew to production on **CrewAI AMP** (Agent Management Platform) in minutes.
<Steps>
<Step title="Build locally">
Scaffold and test your crew or flow:
```bash
crewai create crew my_crew
cd my_crew
crewai run
```
</Step>
<Step title="Prepare for deployment">
Ensure your project structure is ready:
```bash
crewai deploy --prepare
```
See the [preparation guide](/en/enterprise/guides/prepare-for-deployment) for details on project structure and requirements.
</Step>
<Step title="Deploy to AMP">
Push to the CrewAI AMP platform:
```bash
crewai deploy
```
You can also deploy via [GitHub integration](/en/enterprise/guides/deploy-to-amp) or [Crew Studio](/en/enterprise/guides/enable-crew-studio).
</Step>
<Step title="Access via API">
Your deployed crew gets a REST API endpoint. Integrate it into any application:
```bash
curl -X POST https://app.crewai.com/api/v1/crews/<crew-id>/kickoff \
-H "Authorization: Bearer $CREWAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {"topic": "AI agents"}}'
```
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/deploy-to-amp">
Full deployment guide — CLI, GitHub, and Crew Studio methods.
</Card>
<Card title="AMP introduction" icon="globe" href="/en/enterprise/introduction">
Platform overview — what AMP provides for production crews.
</Card>
</CardGroup>
---
## 4. Enterprise Features
CrewAI AMP is built for production teams. Here's what you get beyond deployment.
<CardGroup cols={2}>
<Card title="Observability" icon="chart-line">
Detailed execution traces, logs, and performance metrics for every crew run. Monitor agent decisions, tool calls, and task completion in real time.
</Card>
<Card title="Crew Studio" icon="paintbrush">
No-code/low-code interface to create, customize, and deploy crews visually — then export to code or deploy directly.
</Card>
<Card title="Webhook Streaming" icon="webhook">
Stream real-time events from crew executions to your systems. Integrate with Slack, Zapier, or any webhook consumer.
</Card>
<Card title="Team Management" icon="users">
SSO, RBAC, and organization-level controls. Manage who can create, deploy, and access crews across your team.
</Card>
<Card title="Tool Repository" icon="toolbox">
Publish and share custom tools across your organization. Install community tools from the registry.
</Card>
<Card title="Factory (Self-Hosted)" icon="server">
Run CrewAI AMP on your own infrastructure. Full platform capabilities with data residency and compliance controls.
</Card>
</CardGroup>
<AccordionGroup>
<Accordion title="Who is AMP for?">
AMP is for teams that need to move AI agent workflows from prototypes to production — with observability, access controls, and scalable infrastructure. Whether you're a startup or enterprise, AMP handles the operational complexity so you can focus on building agents.
</Accordion>
<Accordion title="What deployment options are available?">
- **Cloud (app.crewai.com)** — managed by CrewAI, fastest path to production
- **Factory (self-hosted)** — run on your own infrastructure for full data control
- **Hybrid** — mix cloud and self-hosted based on sensitivity requirements
</Accordion>
<Accordion title="How does pricing work?">
Sign up at [app.crewai.com](https://app.crewai.com) to see current plans. Enterprise and Factory pricing is available on request.
</Accordion>
</AccordionGroup>
<Card title="Explore CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Sign up and deploy your first crew to production.
</Card>

View File

@@ -79,6 +79,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -127,7 +128,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -553,6 +555,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -601,7 +604,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -1027,6 +1031,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -1075,7 +1080,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -1501,6 +1507,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -1549,7 +1556,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -1975,6 +1983,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -2023,7 +2032,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -2449,6 +2459,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -2497,7 +2508,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -2921,6 +2933,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -2969,7 +2982,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -3393,6 +3407,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -3441,7 +3456,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -3866,6 +3882,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -3914,7 +3931,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -4340,6 +4358,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -4388,7 +4407,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -4812,6 +4832,7 @@
"group": "Get Started",
"pages": [
"en/introduction",
"en/guides/coding-tools/build-with-ai",
"en/skills",
"en/installation",
"en/quickstart"
@@ -4860,7 +4881,8 @@
"group": "Coding Tools",
"icon": "terminal",
"pages": [
"en/guides/coding-tools/agents-md"
"en/guides/coding-tools/agents-md",
"en/guides/coding-tools/build-with-ai"
]
},
{
@@ -5317,6 +5339,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -5775,6 +5798,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -6233,6 +6257,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -6691,6 +6716,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -7149,6 +7175,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -7607,6 +7634,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -8064,6 +8092,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -8521,6 +8550,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -8978,6 +9008,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -9434,6 +9465,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -9890,6 +9922,7 @@
"group": "Começando",
"pages": [
"pt-BR/introduction",
"pt-BR/guides/coding-tools/build-with-ai",
"pt-BR/skills",
"pt-BR/installation",
"pt-BR/quickstart"
@@ -10377,6 +10410,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -10847,6 +10881,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -11317,6 +11352,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -11787,6 +11823,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -12257,6 +12294,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -12727,6 +12765,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -13196,6 +13235,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -13665,6 +13705,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -14134,6 +14175,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -14602,6 +14644,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -15070,6 +15113,7 @@
"group": "시작 안내",
"pages": [
"ko/introduction",
"ko/guides/coding-tools/build-with-ai",
"ko/skills",
"ko/installation",
"ko/quickstart"
@@ -15569,6 +15613,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -16039,6 +16084,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -16509,6 +16555,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -16979,6 +17026,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -17449,6 +17497,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -17919,6 +17968,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -18388,6 +18438,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -18857,6 +18908,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -19326,6 +19378,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -19794,6 +19847,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"
@@ -20262,6 +20316,7 @@
"group": "البدء",
"pages": [
"ar/introduction",
"ar/guides/coding-tools/build-with-ai",
"ar/skills",
"ar/installation",
"ar/quickstart"

View File

@@ -0,0 +1,206 @@
---
title: "Build with AI"
description: "Everything AI coding agents need to build, deploy, and scale with CrewAI — skills, machine-readable docs, deployment, and enterprise features."
icon: robot
mode: "wide"
---
# Build with AI
CrewAI is AI-native. This page brings together everything an AI coding agent needs to build with CrewAI — whether you're Claude Code, Codex, Cursor, Gemini CLI, or any other assistant helping a developer ship crews and flows.
### Supported Coding Agents
<CardGroup cols={5}>
<Card title="Claude Code" icon="message-bot" color="#D97706" />
<Card title="Cursor" icon="arrow-pointer" color="#3B82F6" />
<Card title="Codex" icon="terminal" color="#10B981" />
<Card title="Windsurf" icon="wind" color="#06B6D4" />
<Card title="Gemini CLI" icon="sparkles" color="#8B5CF6" />
</CardGroup>
<Note>
This page is designed to be consumed by both humans and AI assistants. If you're a coding agent, start with **Skills** to get CrewAI context, then use **llms.txt** for full docs access.
</Note>
---
## 1. Skills — Teach Your Agent CrewAI
**Skills** are instruction packs that give coding agents deep CrewAI knowledge — how to scaffold Flows, configure Crews, use tools, and follow framework conventions.
<Tabs>
<Tab title="Claude Code (Plugin Marketplace)">
<img src="https://cdn.simpleicons.org/anthropic/D97706" alt="Anthropic" width="28" style={{display: "inline", verticalAlign: "middle", marginRight: "8px"}} />
CrewAI skills are available in the **Claude Code plugin marketplace** — the same distribution channel used by top AI-native companies:
```
/plugin marketplace add crewAIInc/skills
```
</Tab>
<Tab title="npx (Any Agent)">
Works with Claude Code, Codex, Cursor, Gemini CLI, or any coding agent:
```shell
npx skills add crewaiinc/skills
```
Pulls from the [skills.sh registry](https://skills.sh/crewaiinc/skills).
</Tab>
</Tabs>
<Steps>
<Step title="Install the official skill pack">
Use either method above — the Claude Code plugin marketplace or `npx skills add`. Both install the official [crewAIInc/skills](https://github.com/crewAIInc/skills) pack.
</Step>
<Step title="Your agent gets instant CrewAI expertise">
The skill pack teaches your agent:
- **Flows** — stateful apps, steps, and crew kickoffs
- **Crews & Agents** — YAML-first patterns, roles, tasks, delegation
- **Tools & Integrations** — search, APIs, MCP servers, and common CrewAI tools
- **Project layout** — CLI scaffolds and repo conventions
- **Up-to-date patterns** — tracks current CrewAI docs and best practices
</Step>
<Step title="Start building">
Your agent can now scaffold and build CrewAI projects without you re-explaining the framework each session.
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Skills concept" icon="bolt" href="/en/concepts/skills">
How skills work in CrewAI agents — injection, activation, and patterns.
</Card>
<Card title="Skills landing page" icon="wand-magic-sparkles" href="/en/skills">
Overview of the crewAIInc/skills pack and what it includes.
</Card>
<Card title="AGENTS.md & coding tools" icon="terminal" href="/en/guides/coding-tools/agents-md">
Set up AGENTS.md for Claude Code, Codex, Cursor, and Gemini CLI.
</Card>
<Card title="Skills registry (skills.sh)" icon="globe" href="https://skills.sh/crewaiinc/skills">
Official listing — skills, install stats, and audits.
</Card>
</CardGroup>
---
## 2. llms.txt — Machine-Readable Docs
CrewAI publishes an `llms.txt` file that gives AI assistants direct access to the full documentation in a machine-readable format.
```
https://docs.crewai.com/llms.txt
```
<Tabs>
<Tab title="What is llms.txt?">
[`llms.txt`](https://llmstxt.org/) is an emerging standard for making documentation consumable by large language models. Instead of scraping HTML, your agent can fetch a single structured text file with all the content it needs.
CrewAI's `llms.txt` is **already live** — your agent can use it right now.
</Tab>
<Tab title="How to use it">
Point your coding agent at the URL when it needs CrewAI reference docs:
```
Fetch https://docs.crewai.com/llms.txt for CrewAI documentation.
```
Many coding agents (Claude Code, Cursor, etc.) can fetch URLs directly. The file contains structured documentation covering all CrewAI concepts, APIs, and guides.
</Tab>
<Tab title="Why it matters">
- **No scraping required** — clean, structured content in one request
- **Always up-to-date** — served directly from docs.crewai.com
- **Optimized for LLMs** — formatted for context windows, not browsers
- **Complements skills** — skills teach patterns, llms.txt provides reference
</Tab>
</Tabs>
---
## 3. Deploy to Enterprise
Go from a local crew to production on **CrewAI AMP** (Agent Management Platform) in minutes.
<Steps>
<Step title="Build locally">
Scaffold and test your crew or flow:
```bash
crewai create crew my_crew
cd my_crew
crewai run
```
</Step>
<Step title="Prepare for deployment">
Ensure your project structure is ready:
```bash
crewai deploy --prepare
```
See the [preparation guide](/en/enterprise/guides/prepare-for-deployment) for details on project structure and requirements.
</Step>
<Step title="Deploy to AMP">
Push to the CrewAI AMP platform:
```bash
crewai deploy
```
You can also deploy via [GitHub integration](/en/enterprise/guides/deploy-to-amp) or [Crew Studio](/en/enterprise/guides/enable-crew-studio).
</Step>
<Step title="Access via API">
Your deployed crew gets a REST API endpoint. Integrate it into any application:
```bash
curl -X POST https://app.crewai.com/api/v1/crews/<crew-id>/kickoff \
-H "Authorization: Bearer $CREWAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {"topic": "AI agents"}}'
```
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/deploy-to-amp">
Full deployment guide — CLI, GitHub, and Crew Studio methods.
</Card>
<Card title="AMP introduction" icon="globe" href="/en/enterprise/introduction">
Platform overview — what AMP provides for production crews.
</Card>
</CardGroup>
---
## 4. Enterprise Features
CrewAI AMP is built for production teams. Here's what you get beyond deployment.
<CardGroup cols={2}>
<Card title="Observability" icon="chart-line">
Detailed execution traces, logs, and performance metrics for every crew run. Monitor agent decisions, tool calls, and task completion in real time.
</Card>
<Card title="Crew Studio" icon="paintbrush">
No-code/low-code interface to create, customize, and deploy crews visually — then export to code or deploy directly.
</Card>
<Card title="Webhook Streaming" icon="webhook">
Stream real-time events from crew executions to your systems. Integrate with Slack, Zapier, or any webhook consumer.
</Card>
<Card title="Team Management" icon="users">
SSO, RBAC, and organization-level controls. Manage who can create, deploy, and access crews across your team.
</Card>
<Card title="Tool Repository" icon="toolbox">
Publish and share custom tools across your organization. Install community tools from the registry.
</Card>
<Card title="Factory (Self-Hosted)" icon="server">
Run CrewAI AMP on your own infrastructure. Full platform capabilities with data residency and compliance controls.
</Card>
</CardGroup>
<AccordionGroup>
<Accordion title="Who is AMP for?">
AMP is for teams that need to move AI agent workflows from prototypes to production — with observability, access controls, and scalable infrastructure. Whether you're a startup or enterprise, AMP handles the operational complexity so you can focus on building agents.
</Accordion>
<Accordion title="What deployment options are available?">
- **Cloud (app.crewai.com)** — managed by CrewAI, fastest path to production
- **Factory (self-hosted)** — run on your own infrastructure for full data control
- **Hybrid** — mix cloud and self-hosted based on sensitivity requirements
</Accordion>
<Accordion title="How does pricing work?">
Sign up at [app.crewai.com](https://app.crewai.com) to see current plans. Enterprise and Factory pricing is available on request.
</Accordion>
</AccordionGroup>
<Card title="Explore CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Sign up and deploy your first crew to production.
</Card>

View File

@@ -0,0 +1,206 @@
---
title: "Build with AI"
description: "Everything AI coding agents need to build, deploy, and scale with CrewAI — skills, machine-readable docs, deployment, and enterprise features."
icon: robot
mode: "wide"
---
# Build with AI
CrewAI is AI-native. This page brings together everything an AI coding agent needs to build with CrewAI — whether you're Claude Code, Codex, Cursor, Gemini CLI, or any other assistant helping a developer ship crews and flows.
### Supported Coding Agents
<CardGroup cols={5}>
<Card title="Claude Code" icon="message-bot" color="#D97706" />
<Card title="Cursor" icon="arrow-pointer" color="#3B82F6" />
<Card title="Codex" icon="terminal" color="#10B981" />
<Card title="Windsurf" icon="wind" color="#06B6D4" />
<Card title="Gemini CLI" icon="sparkles" color="#8B5CF6" />
</CardGroup>
<Note>
This page is designed to be consumed by both humans and AI assistants. If you're a coding agent, start with **Skills** to get CrewAI context, then use **llms.txt** for full docs access.
</Note>
---
## 1. Skills — Teach Your Agent CrewAI
**Skills** are instruction packs that give coding agents deep CrewAI knowledge — how to scaffold Flows, configure Crews, use tools, and follow framework conventions.
<Tabs>
<Tab title="Claude Code (Plugin Marketplace)">
<img src="https://cdn.simpleicons.org/anthropic/D97706" alt="Anthropic" width="28" style={{display: "inline", verticalAlign: "middle", marginRight: "8px"}} />
CrewAI skills are available in the **Claude Code plugin marketplace** — the same distribution channel used by top AI-native companies:
```
/plugin marketplace add crewAIInc/skills
```
</Tab>
<Tab title="npx (Any Agent)">
Works with Claude Code, Codex, Cursor, Gemini CLI, or any coding agent:
```shell
npx skills add crewaiinc/skills
```
Pulls from the [skills.sh registry](https://skills.sh/crewaiinc/skills).
</Tab>
</Tabs>
<Steps>
<Step title="Install the official skill pack">
Use either method above — the Claude Code plugin marketplace or `npx skills add`. Both install the official [crewAIInc/skills](https://github.com/crewAIInc/skills) pack.
</Step>
<Step title="Your agent gets instant CrewAI expertise">
The skill pack teaches your agent:
- **Flows** — stateful apps, steps, and crew kickoffs
- **Crews & Agents** — YAML-first patterns, roles, tasks, delegation
- **Tools & Integrations** — search, APIs, MCP servers, and common CrewAI tools
- **Project layout** — CLI scaffolds and repo conventions
- **Up-to-date patterns** — tracks current CrewAI docs and best practices
</Step>
<Step title="Start building">
Your agent can now scaffold and build CrewAI projects without you re-explaining the framework each session.
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Skills concept" icon="bolt" href="/en/concepts/skills">
How skills work in CrewAI agents — injection, activation, and patterns.
</Card>
<Card title="Skills landing page" icon="wand-magic-sparkles" href="/en/skills">
Overview of the crewAIInc/skills pack and what it includes.
</Card>
<Card title="AGENTS.md & coding tools" icon="terminal" href="/en/guides/coding-tools/agents-md">
Set up AGENTS.md for Claude Code, Codex, Cursor, and Gemini CLI.
</Card>
<Card title="Skills registry (skills.sh)" icon="globe" href="https://skills.sh/crewaiinc/skills">
Official listing — skills, install stats, and audits.
</Card>
</CardGroup>
---
## 2. llms.txt — Machine-Readable Docs
CrewAI publishes an `llms.txt` file that gives AI assistants direct access to the full documentation in a machine-readable format.
```
https://docs.crewai.com/llms.txt
```
<Tabs>
<Tab title="What is llms.txt?">
[`llms.txt`](https://llmstxt.org/) is an emerging standard for making documentation consumable by large language models. Instead of scraping HTML, your agent can fetch a single structured text file with all the content it needs.
CrewAI's `llms.txt` is **already live** — your agent can use it right now.
</Tab>
<Tab title="How to use it">
Point your coding agent at the URL when it needs CrewAI reference docs:
```
Fetch https://docs.crewai.com/llms.txt for CrewAI documentation.
```
Many coding agents (Claude Code, Cursor, etc.) can fetch URLs directly. The file contains structured documentation covering all CrewAI concepts, APIs, and guides.
</Tab>
<Tab title="Why it matters">
- **No scraping required** — clean, structured content in one request
- **Always up-to-date** — served directly from docs.crewai.com
- **Optimized for LLMs** — formatted for context windows, not browsers
- **Complements skills** — skills teach patterns, llms.txt provides reference
</Tab>
</Tabs>
---
## 3. Deploy to Enterprise
Go from a local crew to production on **CrewAI AMP** (Agent Management Platform) in minutes.
<Steps>
<Step title="Build locally">
Scaffold and test your crew or flow:
```bash
crewai create crew my_crew
cd my_crew
crewai run
```
</Step>
<Step title="Prepare for deployment">
Ensure your project structure is ready:
```bash
crewai deploy --prepare
```
See the [preparation guide](/en/enterprise/guides/prepare-for-deployment) for details on project structure and requirements.
</Step>
<Step title="Deploy to AMP">
Push to the CrewAI AMP platform:
```bash
crewai deploy
```
You can also deploy via [GitHub integration](/en/enterprise/guides/deploy-to-amp) or [Crew Studio](/en/enterprise/guides/enable-crew-studio).
</Step>
<Step title="Access via API">
Your deployed crew gets a REST API endpoint. Integrate it into any application:
```bash
curl -X POST https://app.crewai.com/api/v1/crews/<crew-id>/kickoff \
-H "Authorization: Bearer $CREWAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {"topic": "AI agents"}}'
```
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/deploy-to-amp">
Full deployment guide — CLI, GitHub, and Crew Studio methods.
</Card>
<Card title="AMP introduction" icon="globe" href="/en/enterprise/introduction">
Platform overview — what AMP provides for production crews.
</Card>
</CardGroup>
---
## 4. Enterprise Features
CrewAI AMP is built for production teams. Here's what you get beyond deployment.
<CardGroup cols={2}>
<Card title="Observability" icon="chart-line">
Detailed execution traces, logs, and performance metrics for every crew run. Monitor agent decisions, tool calls, and task completion in real time.
</Card>
<Card title="Crew Studio" icon="paintbrush">
No-code/low-code interface to create, customize, and deploy crews visually — then export to code or deploy directly.
</Card>
<Card title="Webhook Streaming" icon="webhook">
Stream real-time events from crew executions to your systems. Integrate with Slack, Zapier, or any webhook consumer.
</Card>
<Card title="Team Management" icon="users">
SSO, RBAC, and organization-level controls. Manage who can create, deploy, and access crews across your team.
</Card>
<Card title="Tool Repository" icon="toolbox">
Publish and share custom tools across your organization. Install community tools from the registry.
</Card>
<Card title="Factory (Self-Hosted)" icon="server">
Run CrewAI AMP on your own infrastructure. Full platform capabilities with data residency and compliance controls.
</Card>
</CardGroup>
<AccordionGroup>
<Accordion title="Who is AMP for?">
AMP is for teams that need to move AI agent workflows from prototypes to production — with observability, access controls, and scalable infrastructure. Whether you're a startup or enterprise, AMP handles the operational complexity so you can focus on building agents.
</Accordion>
<Accordion title="What deployment options are available?">
- **Cloud (app.crewai.com)** — managed by CrewAI, fastest path to production
- **Factory (self-hosted)** — run on your own infrastructure for full data control
- **Hybrid** — mix cloud and self-hosted based on sensitivity requirements
</Accordion>
<Accordion title="How does pricing work?">
Sign up at [app.crewai.com](https://app.crewai.com) to see current plans. Enterprise and Factory pricing is available on request.
</Accordion>
</AccordionGroup>
<Card title="Explore CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Sign up and deploy your first crew to production.
</Card>

View File

@@ -0,0 +1,206 @@
---
title: "Build with AI"
description: "Everything AI coding agents need to build, deploy, and scale with CrewAI — skills, machine-readable docs, deployment, and enterprise features."
icon: robot
mode: "wide"
---
# Build with AI
CrewAI is AI-native. This page brings together everything an AI coding agent needs to build with CrewAI — whether you're Claude Code, Codex, Cursor, Gemini CLI, or any other assistant helping a developer ship crews and flows.
### Supported Coding Agents
<CardGroup cols={5}>
<Card title="Claude Code" icon="message-bot" color="#D97706" />
<Card title="Cursor" icon="arrow-pointer" color="#3B82F6" />
<Card title="Codex" icon="terminal" color="#10B981" />
<Card title="Windsurf" icon="wind" color="#06B6D4" />
<Card title="Gemini CLI" icon="sparkles" color="#8B5CF6" />
</CardGroup>
<Note>
This page is designed to be consumed by both humans and AI assistants. If you're a coding agent, start with **Skills** to get CrewAI context, then use **llms.txt** for full docs access.
</Note>
---
## 1. Skills — Teach Your Agent CrewAI
**Skills** are instruction packs that give coding agents deep CrewAI knowledge — how to scaffold Flows, configure Crews, use tools, and follow framework conventions.
<Tabs>
<Tab title="Claude Code (Plugin Marketplace)">
<img src="https://cdn.simpleicons.org/anthropic/D97706" alt="Anthropic" width="28" style={{display: "inline", verticalAlign: "middle", marginRight: "8px"}} />
CrewAI skills are available in the **Claude Code plugin marketplace** — the same distribution channel used by top AI-native companies:
```
/plugin marketplace add crewAIInc/skills
```
</Tab>
<Tab title="npx (Any Agent)">
Works with Claude Code, Codex, Cursor, Gemini CLI, or any coding agent:
```shell
npx skills add crewaiinc/skills
```
Pulls from the [skills.sh registry](https://skills.sh/crewaiinc/skills).
</Tab>
</Tabs>
<Steps>
<Step title="Install the official skill pack">
Use either method above — the Claude Code plugin marketplace or `npx skills add`. Both install the official [crewAIInc/skills](https://github.com/crewAIInc/skills) pack.
</Step>
<Step title="Your agent gets instant CrewAI expertise">
The skill pack teaches your agent:
- **Flows** — stateful apps, steps, and crew kickoffs
- **Crews & Agents** — YAML-first patterns, roles, tasks, delegation
- **Tools & Integrations** — search, APIs, MCP servers, and common CrewAI tools
- **Project layout** — CLI scaffolds and repo conventions
- **Up-to-date patterns** — tracks current CrewAI docs and best practices
</Step>
<Step title="Start building">
Your agent can now scaffold and build CrewAI projects without you re-explaining the framework each session.
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Skills concept" icon="bolt" href="/en/concepts/skills">
How skills work in CrewAI agents — injection, activation, and patterns.
</Card>
<Card title="Skills landing page" icon="wand-magic-sparkles" href="/en/skills">
Overview of the crewAIInc/skills pack and what it includes.
</Card>
<Card title="AGENTS.md & coding tools" icon="terminal" href="/en/guides/coding-tools/agents-md">
Set up AGENTS.md for Claude Code, Codex, Cursor, and Gemini CLI.
</Card>
<Card title="Skills registry (skills.sh)" icon="globe" href="https://skills.sh/crewaiinc/skills">
Official listing — skills, install stats, and audits.
</Card>
</CardGroup>
---
## 2. llms.txt — Machine-Readable Docs
CrewAI publishes an `llms.txt` file that gives AI assistants direct access to the full documentation in a machine-readable format.
```
https://docs.crewai.com/llms.txt
```
<Tabs>
<Tab title="What is llms.txt?">
[`llms.txt`](https://llmstxt.org/) is an emerging standard for making documentation consumable by large language models. Instead of scraping HTML, your agent can fetch a single structured text file with all the content it needs.
CrewAI's `llms.txt` is **already live** — your agent can use it right now.
</Tab>
<Tab title="How to use it">
Point your coding agent at the URL when it needs CrewAI reference docs:
```
Fetch https://docs.crewai.com/llms.txt for CrewAI documentation.
```
Many coding agents (Claude Code, Cursor, etc.) can fetch URLs directly. The file contains structured documentation covering all CrewAI concepts, APIs, and guides.
</Tab>
<Tab title="Why it matters">
- **No scraping required** — clean, structured content in one request
- **Always up-to-date** — served directly from docs.crewai.com
- **Optimized for LLMs** — formatted for context windows, not browsers
- **Complements skills** — skills teach patterns, llms.txt provides reference
</Tab>
</Tabs>
---
## 3. Deploy to Enterprise
Go from a local crew to production on **CrewAI AMP** (Agent Management Platform) in minutes.
<Steps>
<Step title="Build locally">
Scaffold and test your crew or flow:
```bash
crewai create crew my_crew
cd my_crew
crewai run
```
</Step>
<Step title="Prepare for deployment">
Ensure your project structure is ready:
```bash
crewai deploy --prepare
```
See the [preparation guide](/en/enterprise/guides/prepare-for-deployment) for details on project structure and requirements.
</Step>
<Step title="Deploy to AMP">
Push to the CrewAI AMP platform:
```bash
crewai deploy
```
You can also deploy via [GitHub integration](/en/enterprise/guides/deploy-to-amp) or [Crew Studio](/en/enterprise/guides/enable-crew-studio).
</Step>
<Step title="Access via API">
Your deployed crew gets a REST API endpoint. Integrate it into any application:
```bash
curl -X POST https://app.crewai.com/api/v1/crews/<crew-id>/kickoff \
-H "Authorization: Bearer $CREWAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {"topic": "AI agents"}}'
```
</Step>
</Steps>
<CardGroup cols={2}>
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/deploy-to-amp">
Full deployment guide — CLI, GitHub, and Crew Studio methods.
</Card>
<Card title="AMP introduction" icon="globe" href="/en/enterprise/introduction">
Platform overview — what AMP provides for production crews.
</Card>
</CardGroup>
---
## 4. Enterprise Features
CrewAI AMP is built for production teams. Here's what you get beyond deployment.
<CardGroup cols={2}>
<Card title="Observability" icon="chart-line">
Detailed execution traces, logs, and performance metrics for every crew run. Monitor agent decisions, tool calls, and task completion in real time.
</Card>
<Card title="Crew Studio" icon="paintbrush">
No-code/low-code interface to create, customize, and deploy crews visually — then export to code or deploy directly.
</Card>
<Card title="Webhook Streaming" icon="webhook">
Stream real-time events from crew executions to your systems. Integrate with Slack, Zapier, or any webhook consumer.
</Card>
<Card title="Team Management" icon="users">
SSO, RBAC, and organization-level controls. Manage who can create, deploy, and access crews across your team.
</Card>
<Card title="Tool Repository" icon="toolbox">
Publish and share custom tools across your organization. Install community tools from the registry.
</Card>
<Card title="Factory (Self-Hosted)" icon="server">
Run CrewAI AMP on your own infrastructure. Full platform capabilities with data residency and compliance controls.
</Card>
</CardGroup>
<AccordionGroup>
<Accordion title="Who is AMP for?">
AMP is for teams that need to move AI agent workflows from prototypes to production — with observability, access controls, and scalable infrastructure. Whether you're a startup or enterprise, AMP handles the operational complexity so you can focus on building agents.
</Accordion>
<Accordion title="What deployment options are available?">
- **Cloud (app.crewai.com)** — managed by CrewAI, fastest path to production
- **Factory (self-hosted)** — run on your own infrastructure for full data control
- **Hybrid** — mix cloud and self-hosted based on sensitivity requirements
</Accordion>
<Accordion title="How does pricing work?">
Sign up at [app.crewai.com](https://app.crewai.com) to see current plans. Enterprise and Factory pricing is available on request.
</Accordion>
</AccordionGroup>
<Card title="Explore CrewAI AMP →" icon="arrow-right" href="https://app.crewai.com">
Sign up and deploy your first crew to production.
</Card>

View File

@@ -107,6 +107,9 @@ a2a = [
file-processing = [
"crewai-files",
]
signet = [
"signet-auth>=0.5.0",
]
qdrant-edge = [
"qdrant-edge-py>=0.6.0",
]

View File

@@ -0,0 +1,6 @@
"""First-party integrations for CrewAI.
Each subpackage is opt-in and must lazily import any third-party dependencies
so that importing ``crewai.integrations`` has no runtime cost for users who
have not installed the corresponding extra.
"""

View File

@@ -0,0 +1,83 @@
"""Optional Signet integration for CrewAI.
`Signet <https://github.com/Prismer-AI/signet>`_ produces Ed25519-signed,
hash-chained receipts for AI agent tool calls. This integration registers a
:class:`BaseEventListener` that signs a receipt for every governed action
(structured tool, MCP tool execution, A2A delegation) using the paired
``Started``/``Completed`` events emitted by the CrewAI event bus.
The integration is installed as an optional extra::
pip install 'crewai[signet]'
Then enabled with a single call::
from crewai.integrations.signet import install
listener = install(key_name="my-crew-agent")
After installation, every tool call, MCP tool execution, and A2A delegation
produces a signed receipt stored on the returned listener and (optionally)
appended to a local hash-chained audit log by ``signet-auth``.
"""
from __future__ import annotations
from crewai.integrations.signet.config import SignetConfig
from crewai.integrations.signet.listener import Receipt, SignetEventListener
__all__ = ["Receipt", "SignetConfig", "SignetEventListener", "install"]
def install(
key_name: str,
*,
owner: str | None = None,
audit: bool = True,
policy_path: str | None = None,
create_if_missing: bool = True,
tool_events: bool = True,
mcp_events: bool = True,
a2a_events: bool = True,
signing_agent: object | None = None,
) -> SignetEventListener:
"""Install the Signet event listener on the CrewAI event bus.
Args:
key_name: Signet ``SigningAgent`` identity name. If the identity does
not exist yet and ``create_if_missing=True`` (the default), a new
Ed25519 keypair is created and stored under ``~/.signet/keys/``.
owner: Optional owner string used when creating a new identity.
audit: If ``True``, ``signet-auth`` appends every receipt to its local
hash-chained audit log at ``~/.signet/audit/``.
policy_path: Optional path to a Signet policy file that is co-signed
with every receipt.
create_if_missing: If ``True``, create the identity on first use when
no matching key is found. If ``False``, load the existing key only
and raise if it cannot be found.
tool_events: If ``True``, sign structured tool calls
(``tool_usage_started`` / ``tool_usage_finished``).
mcp_events: If ``True``, sign MCP tool executions
(``mcp_tool_execution_started`` / ``mcp_tool_execution_completed``).
a2a_events: If ``True``, sign A2A delegations
(``a2a_delegation_started`` / ``a2a_delegation_completed``).
signing_agent: Optional pre-built ``SigningAgent`` (or a test double
exposing a ``sign(action, params=...)`` method). When provided,
``signet-auth`` is not imported and the extra is not required.
Returns:
The registered :class:`SignetEventListener`. Receipts can be inspected
via ``listener.receipts``.
"""
config = SignetConfig(
key_name=key_name,
owner=owner,
audit=audit,
policy_path=policy_path,
create_if_missing=create_if_missing,
tool_events=tool_events,
mcp_events=mcp_events,
a2a_events=a2a_events,
)
return SignetEventListener(config=config, signing_agent=signing_agent)

View File

@@ -0,0 +1,34 @@
"""Configuration for the optional Signet integration."""
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field
class SignetConfig(BaseModel):
"""User-facing configuration for the Signet listener.
Attributes:
key_name: Signet ``SigningAgent`` identity name.
owner: Optional owner string used when creating a new identity.
audit: Whether signet-auth should append receipts to its hash-chained
audit log.
policy_path: Optional path to a Signet policy file that is co-signed
with every receipt.
create_if_missing: Whether to create the identity on first use when no
matching key is found.
tool_events: Whether to sign structured tool calls.
mcp_events: Whether to sign MCP tool executions.
a2a_events: Whether to sign A2A delegations.
"""
model_config = ConfigDict(extra="forbid", frozen=True)
key_name: str = Field(..., min_length=1)
owner: str | None = None
audit: bool = True
policy_path: str | None = None
create_if_missing: bool = True
tool_events: bool = True
mcp_events: bool = True
a2a_events: bool = True

View File

@@ -0,0 +1,326 @@
"""Signet event listener that signs paired CrewAI action events.
The listener subscribes to the paired ``Started``/``Completed`` events emitted
for structured tool calls, MCP tool executions, and A2A delegations. When a
``Completed`` event fires, it correlates the two payloads via the CrewAI event
scope (``event.started_event_id``) and produces a single Ed25519-signed Signet
receipt covering the input and the output.
The ``signet_auth`` dependency is **lazy-imported**. If the ``crewai[signet]``
extra is not installed and no ``signing_agent`` is injected, a clear
:class:`ImportError` is raised the first time a matching event fires. Users
who do not opt in pay no import cost.
"""
from __future__ import annotations
from dataclasses import dataclass
import importlib
import threading
from typing import TYPE_CHECKING, Any, Protocol, TypeVar, runtime_checkable
from crewai.events.base_event_listener import BaseEventListener
from crewai.events.types.a2a_events import (
A2ADelegationCompletedEvent,
A2ADelegationStartedEvent,
)
from crewai.events.types.mcp_events import (
MCPToolExecutionCompletedEvent,
MCPToolExecutionFailedEvent,
MCPToolExecutionStartedEvent,
)
from crewai.events.types.tool_usage_events import (
ToolUsageErrorEvent,
ToolUsageFinishedEvent,
ToolUsageStartedEvent,
)
from crewai.integrations.signet.config import SignetConfig
if TYPE_CHECKING:
from crewai.events.base_events import BaseEvent
from crewai.events.event_bus import CrewAIEventsBus
_StartedEventT = TypeVar("_StartedEventT")
_SIGNET_INSTALL_HINT: str = (
"The Signet integration requires the `signet-auth` package. Install the "
"optional extra with `pip install 'crewai[signet]'` or inject a "
"`signing_agent` with a `.sign(action, params=...)` method."
)
@runtime_checkable
class SigningAgentProtocol(Protocol):
"""Minimal protocol satisfied by ``signet_auth.SigningAgent``.
Any object exposing a ``sign(action, params=...)`` method returning a
receipt (typically a mapping) is accepted. This keeps the listener
decoupled from ``signet-auth`` for testing and for alternative backends.
"""
def sign(
self, action: str, *, params: dict[str, Any]
) -> Any: # pragma: no cover - protocol
...
@dataclass
class Receipt:
"""A signed receipt produced by the listener.
Attributes:
kind: One of ``"tool"``, ``"mcp_tool"``, ``"a2a_delegation"``.
action: Action name used when signing (e.g. the tool name).
payload: Canonical dict passed to the signing agent covering both the
input (from the ``Started`` event) and the output (from the
``Completed`` event).
receipt: The raw object returned by the signing agent.
error: ``True`` if the receipt was produced from an error/failed event.
"""
kind: str
action: str
payload: dict[str, Any]
receipt: Any
error: bool = False
class SignetEventListener(BaseEventListener):
"""Event listener that produces Signet receipts for governed actions.
Args:
config: :class:`SignetConfig` controlling which event surfaces are
signed and how the ``SigningAgent`` is built.
signing_agent: Optional pre-built signing agent. When provided the
``signet_auth`` package is not imported. Must expose
``sign(action, params=...)``.
"""
verbose: bool = False
def __init__(
self,
config: SignetConfig,
*,
signing_agent: Any | None = None,
) -> None:
self.config = config
self._injected_signing_agent = signing_agent
self._signing_agent: Any | None = signing_agent
self._pending: dict[str, BaseEvent] = {}
self._pending_lock = threading.Lock()
self.receipts: list[Receipt] = []
self._receipts_lock = threading.Lock()
super().__init__()
def _get_signing_agent(self) -> Any:
"""Return the active signing agent, lazily building one if needed."""
if self._signing_agent is not None:
return self._signing_agent
try:
signet_auth = importlib.import_module("signet_auth")
except ImportError as exc: # pragma: no cover - exercised via stubbed test
raise ImportError(_SIGNET_INSTALL_HINT) from exc
signing_agent_cls = signet_auth.SigningAgent
kwargs: dict[str, Any] = {}
if self.config.audit:
kwargs["audit"] = True
if self.config.policy_path is not None:
kwargs["policy_path"] = self.config.policy_path
if self.config.create_if_missing and hasattr(signing_agent_cls, "create"):
create_kwargs = dict(kwargs)
if self.config.owner is not None:
create_kwargs["owner"] = self.config.owner
self._signing_agent = signing_agent_cls.create(
self.config.key_name, **create_kwargs
)
else:
self._signing_agent = signing_agent_cls(self.config.key_name, **kwargs)
return self._signing_agent
def setup_listeners(self, crewai_event_bus: CrewAIEventsBus) -> None:
"""Register handlers for each enabled event surface."""
if self.config.tool_events:
self._register_tool_handlers(crewai_event_bus)
if self.config.mcp_events:
self._register_mcp_handlers(crewai_event_bus)
if self.config.a2a_events:
self._register_a2a_handlers(crewai_event_bus)
def _register_tool_handlers(self, bus: CrewAIEventsBus) -> None:
@bus.on(ToolUsageStartedEvent)
def _on_tool_start(source: Any, event: ToolUsageStartedEvent) -> None:
self._remember_start(event)
@bus.on(ToolUsageFinishedEvent)
def _on_tool_finish(source: Any, event: ToolUsageFinishedEvent) -> None:
started = self._consume_start(event.started_event_id, ToolUsageStartedEvent)
if started is None:
return
payload = _tool_payload(started, output=event.output, error=None)
self._sign_and_record("tool", started.tool_name, payload, error=False)
@bus.on(ToolUsageErrorEvent)
def _on_tool_error(source: Any, event: ToolUsageErrorEvent) -> None:
started = self._consume_start(event.started_event_id, ToolUsageStartedEvent)
if started is None:
return
payload = _tool_payload(started, output=None, error=str(event.error))
self._sign_and_record("tool", started.tool_name, payload, error=True)
def _register_mcp_handlers(self, bus: CrewAIEventsBus) -> None:
@bus.on(MCPToolExecutionStartedEvent)
def _on_mcp_start(source: Any, event: MCPToolExecutionStartedEvent) -> None:
self._remember_start(event)
@bus.on(MCPToolExecutionCompletedEvent)
def _on_mcp_complete(
source: Any, event: MCPToolExecutionCompletedEvent
) -> None:
started = self._consume_start(
event.started_event_id, MCPToolExecutionStartedEvent
)
if started is None:
return
payload = _mcp_payload(started, result=event.result, error=None)
self._sign_and_record("mcp_tool", started.tool_name, payload, error=False)
@bus.on(MCPToolExecutionFailedEvent)
def _on_mcp_failed(source: Any, event: MCPToolExecutionFailedEvent) -> None:
started = self._consume_start(
event.started_event_id, MCPToolExecutionStartedEvent
)
if started is None:
return
payload = _mcp_payload(started, result=None, error=event.error)
self._sign_and_record("mcp_tool", started.tool_name, payload, error=True)
def _register_a2a_handlers(self, bus: CrewAIEventsBus) -> None:
@bus.on(A2ADelegationStartedEvent)
def _on_a2a_start(source: Any, event: A2ADelegationStartedEvent) -> None:
self._remember_start(event)
@bus.on(A2ADelegationCompletedEvent)
def _on_a2a_complete(source: Any, event: A2ADelegationCompletedEvent) -> None:
started = self._consume_start(
event.started_event_id, A2ADelegationStartedEvent
)
if started is None:
return
payload = _a2a_payload(started, completed=event)
action = f"a2a:{started.agent_id}"
is_error = event.status.lower() not in {"completed", "ok", "success"}
self._sign_and_record("a2a_delegation", action, payload, error=is_error)
def _remember_start(self, event: BaseEvent) -> None:
with self._pending_lock:
self._pending[event.event_id] = event
def _consume_start(
self,
started_event_id: str | None,
expected_type: type[_StartedEventT],
) -> _StartedEventT | None:
if not started_event_id:
return None
with self._pending_lock:
started = self._pending.pop(started_event_id, None)
if not isinstance(started, expected_type):
return None
return started
def _sign_and_record(
self,
kind: str,
action: str,
payload: dict[str, Any],
*,
error: bool,
) -> None:
agent = self._get_signing_agent()
receipt = agent.sign(action, params=payload)
with self._receipts_lock:
self.receipts.append(
Receipt(
kind=kind,
action=action,
payload=payload,
receipt=receipt,
error=error,
)
)
def _tool_payload(
started: ToolUsageStartedEvent,
*,
output: Any,
error: str | None,
) -> dict[str, Any]:
payload: dict[str, Any] = {
"kind": "tool",
"tool_name": started.tool_name,
"tool_class": started.tool_class,
"tool_args": started.tool_args,
"agent_id": started.agent_id,
"agent_role": started.agent_role,
"task_id": started.task_id,
"started_event_id": started.event_id,
}
if error is None:
payload["output"] = output
else:
payload["error"] = error
return payload
def _mcp_payload(
started: MCPToolExecutionStartedEvent,
*,
result: Any,
error: str | None,
) -> dict[str, Any]:
payload: dict[str, Any] = {
"kind": "mcp_tool",
"tool_name": started.tool_name,
"tool_args": started.tool_args,
"server_name": started.server_name,
"server_url": started.server_url,
"transport_type": started.transport_type,
"agent_id": started.agent_id,
"agent_role": started.agent_role,
"task_id": started.task_id,
"started_event_id": started.event_id,
}
if error is None:
payload["result"] = result
else:
payload["error"] = error
return payload
def _a2a_payload(
started: A2ADelegationStartedEvent,
*,
completed: A2ADelegationCompletedEvent,
) -> dict[str, Any]:
return {
"kind": "a2a_delegation",
"endpoint": started.endpoint,
"task_description": started.task_description,
"a2a_agent_id": started.agent_id,
"a2a_agent_name": started.a2a_agent_name,
"context_id": started.context_id,
"is_multiturn": started.is_multiturn,
"turn_number": started.turn_number,
"skill_id": started.skill_id,
"started_event_id": started.event_id,
"status": completed.status,
"result": completed.result,
"error": completed.error,
}

View File

@@ -32,6 +32,7 @@ from pydantic import (
field_validator,
model_validator,
)
from pydantic.functional_serializers import PlainSerializer
from pydantic_core import PydanticCustomError
from typing_extensions import Self
@@ -86,6 +87,22 @@ from crewai.utilities.printer import PRINTER
from crewai.utilities.string_utils import interpolate_only
def _serialize_model_class(v: type[BaseModel] | None) -> dict[str, Any] | None:
"""Serialize a Pydantic model class reference to its JSON schema."""
return v.model_json_schema() if v else None
def _deserialize_model_class(v: Any) -> type[BaseModel] | None:
"""Hydrate a model class reference from checkpoint data."""
if v is None or isinstance(v, type):
return v
if isinstance(v, dict):
from crewai.utilities.pydantic_schema_utils import create_model_from_schema
return create_model_from_schema(v)
return None
class Task(BaseModel):
"""Class that represents a task to be executed.
@@ -141,15 +158,33 @@ class Task(BaseModel):
description="Whether the task should be executed asynchronously or not.",
default=False,
)
output_json: type[BaseModel] | None = Field(
output_json: Annotated[
type[BaseModel] | None,
BeforeValidator(_deserialize_model_class),
PlainSerializer(
_serialize_model_class, return_type=dict | None, when_used="json"
),
] = Field(
description="A Pydantic model to be used to create a JSON output.",
default=None,
)
output_pydantic: type[BaseModel] | None = Field(
output_pydantic: Annotated[
type[BaseModel] | None,
BeforeValidator(_deserialize_model_class),
PlainSerializer(
_serialize_model_class, return_type=dict | None, when_used="json"
),
] = Field(
description="A Pydantic model to be used to create a Pydantic output.",
default=None,
)
response_model: type[BaseModel] | None = Field(
response_model: Annotated[
type[BaseModel] | None,
BeforeValidator(_deserialize_model_class),
PlainSerializer(
_serialize_model_class, return_type=dict | None, when_used="json"
),
] = Field(
description="A Pydantic model for structured LLM outputs using native provider features.",
default=None,
)
@@ -189,7 +224,13 @@ class Task(BaseModel):
description="Whether the task should instruct the agent to return the final answer formatted in Markdown",
default=False,
)
converter_cls: type[Converter] | None = Field(
converter_cls: Annotated[
type[Converter] | None,
BeforeValidator(lambda v: v if v is None or isinstance(v, type) else None),
PlainSerializer(
_serialize_model_class, return_type=dict | None, when_used="json"
),
] = Field(
description="A converter class used to export structured output",
default=None,
)

View File

@@ -0,0 +1,418 @@
"""Tests for the optional Signet integration.
These tests use a lightweight ``FakeSigningAgent`` that satisfies the same
contract as ``signet_auth.SigningAgent`` so the listener can be exercised
without installing the ``crewai[signet]`` extra.
"""
from __future__ import annotations
import sys
import types
from typing import Any
import pytest
from crewai.events.event_bus import crewai_event_bus
from crewai.events.types.a2a_events import (
A2ADelegationCompletedEvent,
A2ADelegationStartedEvent,
)
from crewai.events.types.mcp_events import (
MCPToolExecutionCompletedEvent,
MCPToolExecutionFailedEvent,
MCPToolExecutionStartedEvent,
)
from crewai.events.types.tool_usage_events import (
ToolUsageErrorEvent,
ToolUsageFinishedEvent,
ToolUsageStartedEvent,
)
from crewai.integrations.signet import SignetConfig, SignetEventListener, install
from crewai.integrations.signet.listener import _SIGNET_INSTALL_HINT, Receipt
class FakeSigningAgent:
"""Test double matching the ``signet_auth.SigningAgent`` contract."""
def __init__(self, name: str = "fake") -> None:
self.name = name
self.calls: list[tuple[str, dict[str, Any]]] = []
def sign(self, action: str, *, params: dict[str, Any]) -> dict[str, Any]:
self.calls.append((action, params))
return {
"action": action,
"params": params,
"signature": f"sig-{len(self.calls)}",
"signed_by": self.name,
}
def _install(**kwargs: Any) -> tuple[SignetEventListener, FakeSigningAgent]:
agent = FakeSigningAgent()
listener = install(key_name="test-key", signing_agent=agent, **kwargs)
return listener, agent
def _wait() -> None:
"""Block until all pending event handlers have finished."""
crewai_event_bus.flush(timeout=5.0)
def _emit_tool_pair(
tool_name: str = "some_tool",
*,
with_error: bool = False,
output: Any = "ok",
) -> tuple[ToolUsageStartedEvent, ToolUsageFinishedEvent | ToolUsageErrorEvent]:
started = ToolUsageStartedEvent(
tool_name=tool_name,
tool_args={"x": 1},
tool_class="SomeTool",
agent_id="agent-1",
agent_role="analyst",
)
crewai_event_bus.emit(source=None, event=started)
finished: ToolUsageFinishedEvent | ToolUsageErrorEvent
if with_error:
finished = ToolUsageErrorEvent(
tool_name=tool_name,
tool_args={"x": 1},
tool_class="SomeTool",
agent_id="agent-1",
agent_role="analyst",
error="boom",
started_event_id=started.event_id,
)
else:
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
finished = ToolUsageFinishedEvent(
tool_name=tool_name,
tool_args={"x": 1},
tool_class="SomeTool",
agent_id="agent-1",
agent_role="analyst",
started_at=now,
finished_at=now,
output=output,
started_event_id=started.event_id,
)
crewai_event_bus.emit(source=None, event=finished)
_wait()
return started, finished
def _emit_mcp_pair(
*,
with_error: bool = False,
tool_name: str = "mcp_echo",
) -> tuple[
MCPToolExecutionStartedEvent,
MCPToolExecutionCompletedEvent | MCPToolExecutionFailedEvent,
]:
started = MCPToolExecutionStartedEvent(
server_name="server-a",
server_url="http://localhost:8080",
transport_type="http",
tool_name=tool_name,
tool_args={"q": "hi"},
)
crewai_event_bus.emit(source=None, event=started)
completed: MCPToolExecutionCompletedEvent | MCPToolExecutionFailedEvent
if with_error:
completed = MCPToolExecutionFailedEvent(
server_name="server-a",
tool_name=tool_name,
tool_args={"q": "hi"},
error="server crashed",
started_event_id=started.event_id,
)
else:
completed = MCPToolExecutionCompletedEvent(
server_name="server-a",
tool_name=tool_name,
tool_args={"q": "hi"},
result={"echo": "hi"},
started_event_id=started.event_id,
)
crewai_event_bus.emit(source=None, event=completed)
_wait()
return started, completed
def _emit_a2a_pair(
*,
status: str = "completed",
) -> tuple[A2ADelegationStartedEvent, A2ADelegationCompletedEvent]:
started = A2ADelegationStartedEvent(
endpoint="https://remote/agent",
task_description="summarize",
agent_id="remote-agent-1",
context_id="ctx-1",
)
crewai_event_bus.emit(source=None, event=started)
completed = A2ADelegationCompletedEvent(
status=status,
result="done" if status == "completed" else None,
error=None if status == "completed" else "refused",
context_id="ctx-1",
endpoint="https://remote/agent",
started_event_id=started.event_id,
)
crewai_event_bus.emit(source=None, event=completed)
_wait()
return started, completed
class TestSignetConfig:
def test_defaults(self) -> None:
cfg = SignetConfig(key_name="k")
assert cfg.key_name == "k"
assert cfg.audit is True
assert cfg.create_if_missing is True
assert cfg.tool_events and cfg.mcp_events and cfg.a2a_events
def test_key_name_required(self) -> None:
with pytest.raises(ValueError):
SignetConfig(key_name="")
def test_frozen(self) -> None:
cfg = SignetConfig(key_name="k")
with pytest.raises(Exception):
cfg.key_name = "other" # type: ignore[misc]
class TestToolSigning:
def test_signs_one_receipt_per_tool_call(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, agent = _install()
started, finished = _emit_tool_pair(output={"answer": 42})
assert len(listener.receipts) == 1
rec = listener.receipts[0]
assert isinstance(rec, Receipt)
assert rec.kind == "tool"
assert rec.action == "some_tool"
assert rec.error is False
assert rec.payload["tool_name"] == "some_tool"
assert rec.payload["tool_args"] == {"x": 1}
assert rec.payload["output"] == {"answer": 42}
assert rec.payload["started_event_id"] == started.event_id
assert rec.payload["agent_id"] == "agent-1"
assert rec.receipt["signature"] == "sig-1"
assert agent.calls[0][0] == "some_tool"
def test_signs_error_event(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_tool_pair(with_error=True)
assert len(listener.receipts) == 1
rec = listener.receipts[0]
assert rec.error is True
assert rec.payload["error"] == "boom"
assert "output" not in rec.payload
def test_finished_without_started_is_skipped(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
orphan = ToolUsageFinishedEvent(
tool_name="orphan",
tool_args={},
started_at=now,
finished_at=now,
output="x",
started_event_id="does-not-exist",
)
crewai_event_bus.emit(source=None, event=orphan)
assert listener.receipts == []
def test_pairs_are_independent_across_calls(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_tool_pair(tool_name="t1", output="a")
_emit_tool_pair(tool_name="t2", output="b")
actions = [r.action for r in listener.receipts]
outputs = [r.payload["output"] for r in listener.receipts]
assert actions == ["t1", "t2"]
assert outputs == ["a", "b"]
class TestMCPSigning:
def test_signs_mcp_tool_execution(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_mcp_pair()
assert len(listener.receipts) == 1
rec = listener.receipts[0]
assert rec.kind == "mcp_tool"
assert rec.action == "mcp_echo"
assert rec.payload["server_name"] == "server-a"
assert rec.payload["result"] == {"echo": "hi"}
assert rec.error is False
def test_signs_mcp_failure(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_mcp_pair(with_error=True)
assert len(listener.receipts) == 1
rec = listener.receipts[0]
assert rec.error is True
assert rec.payload["error"] == "server crashed"
class TestA2ASigning:
def test_signs_successful_a2a_delegation(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_a2a_pair(status="completed")
assert len(listener.receipts) == 1
rec = listener.receipts[0]
assert rec.kind == "a2a_delegation"
assert rec.action == "a2a:remote-agent-1"
assert rec.payload["status"] == "completed"
assert rec.payload["endpoint"] == "https://remote/agent"
assert rec.error is False
def test_flags_failed_a2a_delegation_as_error(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install()
_emit_a2a_pair(status="failed")
assert len(listener.receipts) == 1
assert listener.receipts[0].error is True
assert listener.receipts[0].payload["status"] == "failed"
class TestSurfaceToggles:
def test_disabling_tool_events_skips_tool_signing(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install(tool_events=False)
_emit_tool_pair()
_emit_mcp_pair()
assert len(listener.receipts) == 1
assert listener.receipts[0].kind == "mcp_tool"
def test_disabling_mcp_events_skips_mcp_signing(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install(mcp_events=False)
_emit_tool_pair()
_emit_mcp_pair()
assert len(listener.receipts) == 1
assert listener.receipts[0].kind == "tool"
def test_disabling_a2a_events_skips_a2a_signing(self) -> None:
with crewai_event_bus.scoped_handlers():
listener, _ = _install(a2a_events=False)
_emit_a2a_pair()
assert listener.receipts == []
class TestLazyImport:
def test_missing_signet_auth_raises_clear_import_error(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""When no signing_agent is injected and signet_auth isn't installed,
``_get_signing_agent`` must raise a clear ImportError — not at import
or registration time.
"""
monkeypatch.setitem(sys.modules, "signet_auth", None)
with crewai_event_bus.scoped_handlers():
listener = install(key_name="real-key")
assert listener.receipts == []
with pytest.raises(ImportError, match="signet-auth"):
listener._get_signing_agent()
def test_builds_signing_agent_from_fake_signet_auth(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""If signet_auth is importable, SigningAgent.create is used with the
config-derived kwargs."""
captured: dict[str, Any] = {}
class _SigningAgent:
def __init__(self, name: str, **kwargs: Any) -> None:
self.name = name
self.kwargs = kwargs
@classmethod
def create(cls, name: str, **kwargs: Any) -> "_SigningAgent":
captured["create"] = (name, kwargs)
return cls(name, **kwargs)
def sign(self, action: str, *, params: dict[str, Any]) -> dict[str, Any]:
return {"action": action, "params": params, "by": self.name}
fake_module = types.ModuleType("signet_auth")
fake_module.SigningAgent = _SigningAgent # type: ignore[attr-defined]
monkeypatch.setitem(sys.modules, "signet_auth", fake_module)
with crewai_event_bus.scoped_handlers():
listener = install(
key_name="team-agent",
owner="alice",
audit=True,
policy_path="/tmp/policy.yaml",
)
agent = listener._get_signing_agent()
assert captured["create"][0] == "team-agent"
assert captured["create"][1] == {
"audit": True,
"policy_path": "/tmp/policy.yaml",
"owner": "alice",
}
assert isinstance(agent, _SigningAgent)
# Subsequent calls must reuse the same instance.
assert listener._get_signing_agent() is agent
def test_loads_existing_identity_when_create_if_missing_false(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
"""When ``create_if_missing=False`` the listener instantiates
``SigningAgent`` directly instead of calling ``create``."""
init_args: dict[str, Any] = {}
class _SigningAgent:
def __init__(self, name: str, **kwargs: Any) -> None:
init_args["name"] = name
init_args["kwargs"] = kwargs
def sign(self, action: str, *, params: dict[str, Any]) -> dict[str, Any]:
return {"action": action, "params": params}
fake_module = types.ModuleType("signet_auth")
fake_module.SigningAgent = _SigningAgent # type: ignore[attr-defined]
monkeypatch.setitem(sys.modules, "signet_auth", fake_module)
with crewai_event_bus.scoped_handlers():
listener = install(
key_name="existing-agent",
create_if_missing=False,
audit=False,
)
listener._get_signing_agent()
assert init_args["name"] == "existing-agent"
assert init_args["kwargs"] == {}
def test_hint_message_mentions_extra(self) -> None:
assert "crewai[signet]" in _SIGNET_INSTALL_HINT

20
uv.lock generated
View File

@@ -13,7 +13,7 @@ resolution-markers = [
]
[options]
exclude-newer = "2026-04-18T07:00:00Z"
exclude-newer = "2026-04-18T00:00:00Z"
[manifest]
members = [
@@ -1330,6 +1330,9 @@ qdrant = [
qdrant-edge = [
{ name = "qdrant-edge-py" },
]
signet = [
{ name = "signet-auth" },
]
tools = [
{ name = "crewai-tools" },
]
@@ -1387,6 +1390,7 @@ requires-dist = [
{ name = "qdrant-client", extras = ["fastembed"], marker = "extra == 'qdrant'", specifier = "~=1.14.3" },
{ name = "qdrant-edge-py", marker = "extra == 'qdrant-edge'", specifier = ">=0.6.0" },
{ name = "regex", specifier = "~=2026.1.15" },
{ name = "signet-auth", marker = "extra == 'signet'", specifier = ">=0.5.0" },
{ name = "textual", specifier = ">=7.5.0" },
{ name = "tiktoken", marker = "extra == 'embeddings'", specifier = "~=0.8.0" },
{ name = "tokenizers", specifier = ">=0.21,<1" },
@@ -1395,7 +1399,7 @@ requires-dist = [
{ name = "uv", specifier = "~=0.11.6" },
{ name = "voyageai", marker = "extra == 'voyageai'", specifier = "~=0.3.5" },
]
provides-extras = ["a2a", "anthropic", "aws", "azure-ai-inference", "bedrock", "docling", "embeddings", "file-processing", "google-genai", "litellm", "mem0", "openpyxl", "pandas", "qdrant", "qdrant-edge", "tools", "voyageai", "watson"]
provides-extras = ["a2a", "anthropic", "aws", "azure-ai-inference", "bedrock", "docling", "embeddings", "file-processing", "google-genai", "litellm", "mem0", "openpyxl", "pandas", "qdrant", "qdrant-edge", "signet", "tools", "voyageai", "watson"]
[[package]]
name = "crewai-devtools"
@@ -8095,6 +8099,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
]
[[package]]
name = "signet-auth"
version = "0.9.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b8/09/68036ddb2d00985d1081f205e2480368ed28294a864bc87e44796ec6685b/signet_auth-0.9.0.tar.gz", hash = "sha256:c650db7d16236448234a2d356245e19bdb5b48fe78cc3436311db8b002867885", size = 88768, upload-time = "2026-04-13T09:33:56.925Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/8d/800651df03709729ae52c89310c71eaf3aea4efadb183e67a9d7f002cba6/signet_auth-0.9.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:013152b26415ceb89cf2969e69a03aa254328f2d7f656a080842c967e2c7d1e1", size = 1730524, upload-time = "2026-04-13T09:33:49.261Z" },
{ url = "https://files.pythonhosted.org/packages/78/61/59f87d18c76f9dff467b62a48afade139460c090f91ad13c56cb52dd2b46/signet_auth-0.9.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:4c3ce87dc6265993ddc4f56d6ef5ad867b66d74cc8713c23f1fe47d6317b1d55", size = 1614461, upload-time = "2026-04-13T09:33:51.016Z" },
{ url = "https://files.pythonhosted.org/packages/39/a4/b0d887fda7e25647629be600cd38e8f1fc129f6bc4c5bdefdac61531a915/signet_auth-0.9.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2950761b4199d764902520749c60d668ae7ade91de8347e89253a94f102c94d", size = 1802423, upload-time = "2026-04-13T09:33:53.338Z" },
{ url = "https://files.pythonhosted.org/packages/e4/60/71f8884256523a57646fd0e216b7a267cae69e4751f4bf0e5703bd9b1d5f/signet_auth-0.9.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2139507c8c0d44b74fa6d73f1812446223c1fa381f0d2e811a9a411302378deb", size = 1859359, upload-time = "2026-04-13T09:33:55.506Z" },
]
[[package]]
name = "singlestoredb"
version = "1.16.9"