# Create an access token Source: https://docs-platform.crewai.com/api-reference/authentication/create-an-access-token /openapi/platform-auth.yaml post /oauth/token Exchange service account client credentials for an opaque bearer access token. Use HTTP Basic auth with `client_id` as the username and `client_secret` as the password; the header is `Authorization: Basic `. # Introduction Source: https://docs-platform.crewai.com/api/introduction Build against the supported CrewAI Platform public API. CrewAI Platform provides stable HTTP contracts for automation, integrations, and agent-facing workflows. **Beta:** The CrewAI Platform API is currently in beta and may change as we continue to improve it. The current public contract is `v1`. CrewAI Platform endpoints are available under `/api/v1` on your CrewAI Platform host. ## Authentication Use a service account to obtain an access token, then send that token as a bearer credential when calling protected endpoints. # Error responses Source: https://docs-platform.crewai.com/api/problems Error responses returned by the CrewAI Platform API. When a request fails, the Platform API returns an `errors` array. Each item includes a stable `code`, an HTTP `status`, and a `detail` message with request-specific context. Use the pages in this section to understand each error code and what to change before retrying. # Bad request Source: https://docs-platform.crewai.com/api/problems/bad_request # Bad request The request could not be processed because it was malformed or missing required request data. ## When It Happens This usually means the request body, query string, headers, or required parameters are invalid before endpoint-specific validation can run. ## How To Fix Review the endpoint contract, required parameters, request body shape, and content type before retrying. # Conflict Source: https://docs-platform.crewai.com/api/problems/conflict # Conflict The request was valid, but it could not be completed because of the current state of the target resource. ## When It Happens This usually means the resource exists, but its current lifecycle state or invariants prevent the requested action. ## How To Fix Inspect the `detail` message, resolve the resource state conflict, and retry the request when the action is valid again. # Internal error Source: https://docs-platform.crewai.com/api/problems/internal_error # Internal error An unexpected server-side failure prevented the request from completing. ## When It Happens This means the platform encountered an unexpected condition while processing a valid request. ## How To Fix Retry the request after a short delay. If the problem continues, contact support with the request details and timestamp. # Not found Source: https://docs-platform.crewai.com/api/problems/not_found # Not found The requested resource does not exist or is not available at the requested path. ## When It Happens This can happen when the URL is incorrect, the resource identifier does not exist, or the resource is not visible through the public API. ## How To Fix Check the endpoint path and resource identifier, then retry with a resource that exists and is available to the request. # Unauthorized Source: https://docs-platform.crewai.com/api/problems/unauthorized # Unauthorized The request could not be authenticated. ## When It Happens This usually means required authentication credentials are missing, invalid, expired, or revoked. ## How To Fix Provide valid active credentials and retry the request. # Validation error Source: https://docs-platform.crewai.com/api/problems/validation_error # Validation error The request was understood, but one or more submitted values failed validation. ## When It Happens This usually means a submitted field is missing, malformed, out of range, duplicated, or conflicts with another value. ## How To Fix Inspect the `detail` message for the field-specific issue, update the submitted values, and retry the request. # Service accounts Source: https://docs-platform.crewai.com/api/service-account # Service accounts Service accounts let an organization create credentials for server-side API clients without tying those credentials to a human user. A service account has long-lived client credentials. API clients exchange those credentials for short-lived opaque access tokens, then use the access tokens to call protected CrewAI Platform API endpoints. ## Create a service account 1. Open **Settings** in your organization. 2. Open **Service Accounts**. 3. In the **Create service account** form, enter a descriptive name, such as `Production automation`. 4. Optionally enter a description. 5. Click **Create service account**. 6. Copy the generated **Client ID** and **Client secret** from the credentials dialog. 7. Store the client secret in the secret storage system your organization uses for server-side credentials. The client secret is shown only once. After you close the credentials dialog, CrewAI cannot show that same secret again. ## Rotate a client secret Rotate a service account to generate a new client secret. 1. Open **Settings** in your organization. 2. Open **Service Accounts**. 3. Click **View details** for the service account. 4. Click **Rotate**. 5. Copy the new **Client secret** from the credentials dialog. 6. Store the new secret in the secret storage system your organization uses for server-side credentials. During rotation, the previous secret remains valid until the expiration time shown in the service account details. Use that window to update the systems that depend on the secret. The new client secret is shown only once. If you close the credentials dialog before storing it, rotate again to generate another secret. ## If you lose the secret CrewAI stores only a one-way digest of the client secret. The original secret cannot be recovered. If you lose the secret, rotate the service account to generate a new one. ## Get an access token Use the OAuth 2.0 client credentials flow to exchange a service account's `client_id` and `client_secret` for an access token. The token endpoint is not versioned: ```http theme={null} POST /oauth/token ``` Use HTTP Basic authentication with the service account client ID as the username and the client secret as the password. The `Authorization` header value is `Basic `. ```bash theme={null} curl -X POST "https://app.crewai.com/oauth/token" \ -H "Authorization: Basic $(printf '%s:%s' "$CLIENT_ID" "$CLIENT_SECRET" | base64)" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" ``` A successful response returns an opaque bearer token: ```json theme={null} { "access_token": "crewai_sacat_...", "token_type": "Bearer", "expires_in": 3600 } ``` CrewAI does not issue refresh tokens for service account client credentials. The access token is shown only in the token response. CrewAI stores only a one-way digest of the access token, so the original token cannot be recovered from the database. ## Call the API with an access token Send the access token as a bearer token when calling protected Platform API endpoints: ```bash theme={null} curl "https://app.crewai.com/api/v1/status" \ -H "Authorization: Bearer $ACCESS_TOKEN" ``` Access tokens are currently scoped to the CrewAI Platform API. They are not JWTs and clients should treat them as opaque strings. ## Cache access tokens Access tokens are short-lived. The token response includes `expires_in`, which tells clients how many seconds the issued token remains valid. CrewAI currently issues service account access tokens with a 3600-second lifetime. Clients should cache and reuse an access token until it is close to expiration. Do not call `/oauth/token` before every API request. The token endpoint is rate-limited to protect the authentication service and to encourage token reuse. If a client receives a rate-limit response, it should back off and reuse a cached token if one is still valid. ## Token request errors `/oauth/token` returns OAuth 2.0-style errors, not the CrewAI API `data` / `errors` envelope. Example: ```json theme={null} { "error": "invalid_client", "error_description": "Client authentication failed." } ``` Protected `/api/v1/...` resource endpoints continue to return CrewAI API error envelopes. Missing, expired, revoked, or invalid bearer tokens return `401 Unauthorized` with a `WWW-Authenticate: Bearer` header. ## Revoke a service account Revoke a service account when it should no longer be used. 1. Open **Settings** in your organization. 2. Open **Service Accounts**. 3. Click **View details** for the service account. 4. Click **Revoke**. 5. Optionally enter a reason. 6. Confirm the revocation. Revocation disables the service account immediately. Revoked service accounts cannot obtain new access tokens, and existing access tokens for a revoked service account are rejected. # Create an Automation Source: https://docs-platform.crewai.com/api/v1/reference/automations/create-an-automation /openapi/platform-v1.yaml post /api/v1/automations Creates an Automation from an uploaded ZIP source artifact. The upload is consumed after the deployment is created. # Delete an Automation Source: https://docs-platform.crewai.com/api/v1/reference/automations/delete-an-automation /openapi/platform-v1.yaml delete /api/v1/automations/{id} Enqueues an Automation in the authenticated service account's organization for deletion. # Get an Automation Source: https://docs-platform.crewai.com/api/v1/reference/automations/get-an-automation /openapi/platform-v1.yaml get /api/v1/automations/{id} Returns an Automation in the organization associated with the authenticated service account. # List Automations Source: https://docs-platform.crewai.com/api/v1/reference/automations/list-automations /openapi/platform-v1.yaml get /api/v1/automations Returns automations that belong to the organization associated with the authenticated service account. # Redeploy an Automation Source: https://docs-platform.crewai.com/api/v1/reference/automations/redeploy-an-automation /openapi/platform-v1.yaml post /api/v1/automations/{id}/redeploy Redeploys an existing Automation. An optional upload_id replaces the ZIP source and is consumed after the deployment is updated. # Upload an Automation ZIP Source: https://docs-platform.crewai.com/api/v1/reference/automations/upload-an-automation-zip /openapi/platform-v1.yaml post /api/v1/automation-uploads Uploads a ZIP source artifact for a later Automation create or redeploy request. Uploads expire one hour after creation and are scoped to the authenticated service account organization. # A2A on AMP Source: https://docs-platform.crewai.com/platform/en/features/a2a Production-grade Agent-to-Agent communication with distributed state and multi-scheme authentication A2A server agents on AMP are in early release. APIs may change in future versions. ## Overview CrewAI AMP extends the open-source [A2A protocol implementation](https://docs.crewai.com/en/learn/a2a-agent-delegation) with production infrastructure for deploying distributed agents at scale. AMP supports A2A protocol versions 0.2 and 0.3. When you deploy a crew or agent with A2A server configuration to AMP, the platform automatically provisions distributed state management, authentication, multi-transport endpoints, and lifecycle management. For A2A protocol fundamentals, client/server configuration, and authentication schemes, see the [A2A Agent Delegation](https://docs.crewai.com/en/learn/a2a-agent-delegation) documentation. This page covers what AMP adds on top of the open-source implementation. ### Usage Add `A2AServerConfig` to any agent in your crew and deploy to AMP. The platform detects agents with server configuration and automatically registers A2A endpoints, generates agent cards, and provisions the infrastructure described below. ```python theme={null} from crewai import Agent, Crew, Task from crewai.a2a import A2AServerConfig from crewai.a2a.auth import EnterpriseTokenAuth agent = Agent( role="Data Analyst", goal="Analyze datasets and provide insights", backstory="Expert data scientist with statistical analysis skills", llm="gpt-4o", a2a=A2AServerConfig( auth=EnterpriseTokenAuth() ) ) task = Task( description="Analyze the provided dataset", expected_output="Statistical summary with key insights", agent=agent ) crew = Crew(agents=[agent], tasks=[task]) ``` After [deploying to AMP](/platform/en/guides/deploy-to-amp), the platform registers two levels of A2A endpoints: * **Crew-level**: an aggregate agent card at `/.well-known/agent-card.json` where each agent with `A2AServerConfig` is listed as a skill, with a JSON-RPC endpoint at `/a2a` * **Per-agent**: isolated agent cards and JSON-RPC endpoints mounted at `/a2a/agents/{role}/`, each with its own tenancy Clients can interact with the crew as a whole or target a specific agent directly. To route a request to a specific agent through the crew-level endpoint, include `"target_agent"` in the message metadata with the agent's slugified role name (e.g., `"data-analyst"` for an agent with role `"Data Analyst"`). If no `target_agent` is provided, the request is handled by the first agent in the crew. See [A2A Agent Delegation](https://docs.crewai.com/en/learn/a2a-agent-delegation#server-configuration-options) for the full list of `A2AServerConfig` options. Per the A2A protocol, agent cards are publicly accessible to enable discovery. This includes both the crew-level card at `/.well-known/agent-card.json` and per-agent cards at `/a2a/agents/{role}/.well-known/agent-card.json`. Do not include sensitive information in agent names, descriptions, or skill definitions. ### File Inputs and Structured Output A2A on AMP supports passing files and requesting structured output in both directions. Clients can send files as `FilePart`s and request structured responses by embedding a JSON schema in the message. Server agents receive files as `input_files` on the task, and return structured data as `DataPart`s when a schema is provided. See [File Inputs and Structured Output](https://docs.crewai.com/en/learn/a2a-agent-delegation#file-inputs-and-structured-output) for details. ### What AMP Adds Persistent task, context, and result storage OIDC, OAuth2, mTLS, and Enterprise token validation beyond simple bearer tokens Full gRPC server with TLS and authentication Automatic idle detection, expiration, and cleanup of long-running conversations HMAC-SHA256 signed push notifications with replay protection REST, JSON-RPC, and gRPC endpoints served simultaneously from a single deployment *** ## Distributed State Management In the open-source implementation, task and context state lives in memory on a single process. AMP replaces this with persistent, distributed stores. ### Storage Layers | Store | Purpose | | --------------------- | ------------------------------------------------------------------------------- | | **Task Store** | Persists A2A task state and metadata | | **Context Store** | Tracks conversation context, creation time, last activity, and associated tasks | | **Result Store** | Caches task results for retrieval | | **Push Config Store** | Manages webhook subscriptions per task | Multiple A2A deployments are automatically isolated from each other, preventing data collisions when sharing infrastructure. *** ## Enterprise Authentication AMP supports six authentication schemes for incoming A2A requests, configurable per deployment. Authentication works across both HTTP and gRPC transports. | Scheme | Description | Use Case | | ----------------------- | ------------------------------------------------------------------- | ------------------------------- | | **SimpleTokenAuth** | Static bearer token from `AUTH_TOKEN` env var | Development, simple deployments | | **EnterpriseTokenAuth** | Token verification via CrewAI PlusAPI with integration token claims | AMP-to-AMP agent communication | | **OIDCAuth** | OpenID Connect JWT validation with JWKS endpoint caching | Enterprise SSO integration | | **OAuth2ServerAuth** | OAuth2 with configurable scopes | Fine-grained access control | | **APIKeyServerAuth** | API key validation via header or query parameter | Third-party integrations | | **MTLSServerAuth** | Mutual TLS certificate-based authentication | Zero-trust environments | The configured auth scheme automatically populates the agent card's `securitySchemes` and `security` fields. Clients discover authentication requirements by fetching the agent card before making requests. *** ## Extended Agent Cards AMP supports role-based skill visibility through extended agent cards. Unauthenticated users see the standard agent card with public skills. Authenticated users receive an extended card with additional capabilities. This enables patterns like: * Public agents that expose basic skills to anyone, with advanced skills available to authenticated clients * Internal agents that advertise different capabilities based on the caller's identity *** ## gRPC Transport If enabled, AMP provides full gRPC support alongside the default JSON-RPC transport. * **TLS termination** with configurable certificate and key paths * **gRPC reflection** for debugging with tools like `grpcurl` * **Authentication** using the same schemes available for HTTP * **Extension validation** ensuring clients support required protocol extensions * **Version negotiation** across A2A protocol versions 0.2 and 0.3 For deployments exposing multiple agents, AMP automatically allocates per-agent gRPC ports and coordinates TLS, startup, and shutdown across all servers. *** ## Context Lifecycle Management AMP tracks the lifecycle of A2A conversation contexts and automatically manages cleanup. ### Lifecycle States | State | Condition | Action | | ----------- | ------------------------------------ | ---------------------------------------------------------- | | **Active** | Context has recent activity | None | | **Idle** | No activity for a configured period | Marked idle, event emitted | | **Expired** | Context exceeds its maximum lifetime | Marked expired, associated tasks cleaned up, event emitted | A background cleanup task runs hourly to scan for idle and expired contexts. All state transitions emit CrewAI events that integrate with the platform's observability features. *** ## Signed Push Notifications When an A2A agent sends push notifications to a client webhook, AMP signs each request with HMAC-SHA256 to ensure integrity and prevent tampering. ### Signature Headers | Header | Purpose | | --------------------------- | ----------------------------------------------------- | | `X-A2A-Signature` | HMAC-SHA256 signature in `sha256={hex_digest}` format | | `X-A2A-Signature-Timestamp` | Unix timestamp bound to the signature | | `X-A2A-Notification-Token` | Optional notification auth token | ### Security Properties * **Integrity**: payload cannot be modified without invalidating the signature * **Replay protection**: signatures are timestamp-bound with a configurable tolerance window * **Retry with backoff**: failed deliveries retry with exponential backoff *** ## Distributed Event Streaming In the open-source implementation, SSE streaming works within a single process. AMP propagates SSE events across instances so that clients receive updates even when the instance holding the streaming connection differs from the instance executing the task. *** ## Multi-Transport Endpoints AMP serves REST and JSON-RPC by default. gRPC is available as an additional transport if enabled. | Transport | Path Convention | Description | | ------------ | ----------------------------------------------------- | ------------------------------------------ | | **REST** | `/v1/message:send`, `/v1/message:stream`, `/v1/tasks` | Google API conventions | | **JSON-RPC** | Standard A2A JSON-RPC endpoint | Default A2A protocol transport | | **gRPC** | Per-agent port allocation | Optional, high-performance binary protocol | All active transports share the same authentication, version negotiation, and extension validation. Agent cards are generated from agent and crew metadata — roles, goals, and tools become skills and descriptions — and automatically include interfaces for each active transport. They can also be manually configured via `A2AServerConfig`. *** ## Version and Extension Negotiation AMP validates A2A protocol versions and extensions at the transport layer. ### Version Negotiation * Clients send the `A2A-Version` header with their preferred version * AMP validates against supported versions (0.2, 0.3) and falls back to 0.3 if unspecified * The negotiated version is returned in the response headers ### Extension Validation * Clients declare supported extensions via the `X-A2A-Extensions` header * AMP validates that clients support all extensions the agent requires * Requests from clients missing required extensions receive an `UnsupportedExtensionError` *** ## Next Steps * [A2A Agent Delegation](https://docs.crewai.com/en/learn/a2a-agent-delegation) — A2A protocol fundamentals and configuration * [A2UI](https://docs.crewai.com/en/learn/a2ui) — Interactive UI rendering over A2A * [Deploy to AMP](/platform/en/guides/deploy-to-amp) — General deployment guide * [Webhook Streaming](/platform/en/features/webhook-streaming) — Event streaming for deployed automations # Agent Repositories Source: https://docs-platform.crewai.com/platform/en/features/agent-repositories Learn how to use Agent Repositories to share and reuse your agents across teams and projects Agent Repositories allow enterprise users to store, share, and reuse agent definitions across teams and projects. This feature enables organizations to maintain a centralized library of standardized agents, promoting consistency and reducing duplication of effort. Agent Repositories ## Benefits of Agent Repositories * **Standardization**: Maintain consistent agent definitions across your organization * **Reusability**: Create an agent once and use it in multiple crews and projects * **Governance**: Implement organization-wide policies for agent configurations * **Collaboration**: Enable teams to share and build upon each other's work ## Creating and Use Agent Repositories 1. You must have an account at CrewAI, try the [free plan](https://app.crewai.com). 2. Create agents with specific roles and goals for your workflows. 3. Configure tools and capabilities for each specialized assistant. 4. Deploy agents across projects via visual interface or API integration. Agent Repositories ### Loading Agents from Repositories You can load agents from repositories in your code using the `from_repository` parameter to run locally: ```python theme={null} from crewai import Agent # Create an agent by loading it from a repository # The agent is loaded with all its predefined configurations researcher = Agent( from_repository="market-research-agent" ) ``` ### Overriding Repository Settings You can override specific settings from the repository by providing them in the configuration: ```python theme={null} researcher = Agent( from_repository="market-research-agent", goal="Research the latest trends in AI development", # Override the repository goal verbose=True # Add a setting not in the repository ) ``` ### Example: Creating a Crew with Repository Agents ```python theme={null} from crewai import Crew, Agent, Task # Load agents from repositories researcher = Agent( from_repository="market-research-agent" ) writer = Agent( from_repository="content-writer-agent" ) # Create tasks research_task = Task( description="Research the latest trends in AI", agent=researcher ) writing_task = Task( description="Write a comprehensive report based on the research", agent=writer ) # Create the crew crew = Crew( agents=[researcher, writer], tasks=[research_task, writing_task], verbose=True ) # Run the crew result = crew.kickoff() ``` ### Example: Using `kickoff()` with Repository Agents You can also use repository agents directly with the `kickoff()` method for simpler interactions: ```python theme={null} from crewai import Agent from pydantic import BaseModel from typing import List # Define a structured output format class MarketAnalysis(BaseModel): key_trends: List[str] opportunities: List[str] recommendation: str # Load an agent from repository analyst = Agent( from_repository="market-analyst-agent", verbose=True ) # Get a free-form response result = analyst.kickoff("Analyze the AI market in 2025") print(result.raw) # Access the raw response # Get structured output structured_result = analyst.kickoff( "Provide a structured analysis of the AI market in 2025", response_format=MarketAnalysis ) # Access structured data print(f"Key Trends: {structured_result.pydantic.key_trends}") print(f"Recommendation: {structured_result.pydantic.recommendation}") ``` ## Best Practices 1. **Naming Convention**: Use clear, descriptive names for your repository agents 2. **Documentation**: Include comprehensive descriptions for each agent 3. **Tool Management**: Ensure that tools referenced by repository agents are available in your environment 4. **Access Control**: Manage permissions to ensure only authorized team members can modify repository agents ## Organization Management To switch between organizations or see your current organization, use the CrewAI CLI: ```bash theme={null} # View current organization crewai org current # Switch to a different organization crewai org switch # List all available organizations crewai org list ``` When loading agents from repositories, you must be authenticated and switched to the correct organization. If you receive errors, check your authentication status and organization settings using the CLI commands above. # Automations Source: https://docs-platform.crewai.com/platform/en/features/automations Manage, deploy, and monitor your live crews (automations) in one place. ## Overview Automations is the live operations hub for your deployed crews. Use it to deploy from GitHub or a ZIP file, manage environment variables, re‑deploy when needed, and monitor the status of each automation. Automations Overview ## Deployment Methods ### Deploy from GitHub Use this for version‑controlled projects and continuous deployment. Click Configure GitHub and authorize access. Choose the Repository and Branch you want to deploy from. Turn on Automatically deploy new commits to ship updates on every push. Add secrets individually or use Bulk View for multiple variables. Click Deploy to create your live automation. GitHub Deployment ### Deploy from ZIP Ship quickly without Git—upload a compressed package of your project. Select the ZIP archive from your computer. Provide any required variables or keys. Click Deploy to create your live automation. ZIP Deployment ## Automations Dashboard The table lists all live automations with key details: * **CREW**: Automation name * **STATUS**: Online / Failed / In Progress * **URL**: Endpoint for kickoff/status * **TOKEN**: Automation token * **ACTIONS**: Re‑deploy, delete, and more Use the top‑right controls to filter and search: * Search by name * Filter by Status * Filter by Source (GitHub / Studio / ZIP) Once deployed, you can view the automation details and have the **Options** dropdown menu to `chat with this crew`, `Export React Component` and `Export as MCP`. Automations Table ## Best Practices * Prefer GitHub deployments for version control and CI/CD * Use re‑deploy to roll forward after code or config updates or set it to auto-deploy on every push ## Related Deploy a Crew from GitHub or ZIP file. Trigger automations via webhooks or API. Stream real-time events and updates to your systems. Multi-turn chat sessions, streaming, and history for conversational Flows. # Crew Studio Source: https://docs-platform.crewai.com/platform/en/features/crew-studio Build new automations with AI assistance, a visual editor, and integrated testing. ## Overview Crew Studio is an interactive, AI‑assisted workspace for creating new automations from scratch using natural language and a visual workflow editor. Crew Studio Overview ## Prompt‑based Creation * Describe the automation you want; the AI generates agents, tasks, and tools. * Use voice input via the microphone icon if preferred. * Start from built‑in prompts for common use cases. Prompt Builder ## Visual Editor The canvas reflects the workflow as nodes and edges with three supporting panels that allow you to configure the workflow easily without writing code; a.k.a. "**vibe coding AI Agents**". You can use the drag-and-drop functionality to add agents, tasks, and tools to the canvas or you can use the chat section to build the agents. Both approaches share state and can be used interchangeably. * **AI Thoughts (left)**: streaming reasoning as the workflow is designed * **Canvas (center)**: agents and tasks as connected nodes * **Resources (right)**: drag‑and‑drop components (agents, tasks, tools) Visual Canvas ## Execution & Debugging Switch to the Execution view to run and observe the workflow: * Event timeline * Detailed logs (Details, Messages, Raw Data) * Local test runs before publishing Execution View ## Publish & Export * Publish to deploy a live automation * Download source as a ZIP to continue development in code outside Studio A downloaded ZIP is a one-way export. Your Studio project remains the source of truth: changes you make to the downloaded code are not reflected in Studio and cannot be imported back. If you deploy the customized code, it becomes a separate code-sourced automation without the Studio visual editor, versioning, or validation. Publish & Download Once published, you can view the automation details and have the **Options** dropdown menu to `chat with this crew`, `Export React Component` and `Export as MCP`. Published Automation ## Best Practices * Iterate quickly in Studio; publish only when stable * Keep tools constrained to minimum permissions needed * Use Traces to validate behavior and performance ## Related Enable Crew Studio. Build a Crew. Deploy a Crew from GitHub or ZIP file. Export a React Component. # Flow HITL Management Source: https://docs-platform.crewai.com/platform/en/features/flow-hitl-management Enterprise-grade human review for Flows with email-first notifications, routing rules, and auto-response capabilities Flow HITL Management features require the `@human_feedback` decorator, available in **CrewAI version 1.8.0 or higher**. These features apply specifically to **Flows**, not Crews. CrewAI Enterprise provides a comprehensive Human-in-the-Loop (HITL) management system for Flows that transforms AI workflows into collaborative human-AI processes. The platform uses an **email-first architecture** that enables anyone with an email address to respond to review requests—no platform account required. ## Overview Responders can reply directly to notification emails to provide feedback Route requests to specific emails based on method patterns or flow state Configure automatic fallback responses when no human replies in time ### Key Benefits * **Simple mental model**: Email addresses are universal; no need to manage platform users or roles * **External responders**: Anyone with an email can respond, even non-platform users * **Dynamic assignment**: Pull assignee email directly from flow state (e.g., `sales_rep_email`) * **Reduced configuration**: Fewer settings to configure, faster time to value * **Email as primary channel**: Most users prefer responding via email over logging into a dashboard ## Setting Up Human Review Points in Flows Configure human review checkpoints within your Flows using the `@human_feedback` decorator. When execution reaches a review point, the system pauses, notifies the assignee via email, and waits for a response. ```python theme={null} from crewai.flow.flow import Flow, start, listen, or_ from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult class ContentApprovalFlow(Flow): @start() def generate_content(self): return "Generated marketing copy for Q1 campaign..." @human_feedback( message="Please review this content for brand compliance:", emit=["approved", "rejected", "needs_revision"], ) @listen(or_("generate_content", "needs_revision")) def review_content(self): return "Marketing copy for review..." @listen("approved") def publish_content(self, result: HumanFeedbackResult): print(f"Publishing approved content. Reviewer notes: {result.feedback}") @listen("rejected") def archive_content(self, result: HumanFeedbackResult): print(f"Content rejected. Reason: {result.feedback}") ``` For complete implementation details, see the [Human Feedback in Flows](https://docs.crewai.com/en/learn/human-feedback-in-flows) guide. ### Decorator Parameters | Parameter | Type | Description | | --------- | ----------- | --------------------------------------------------- | | `message` | `str` | The message displayed to the human reviewer | | `emit` | `list[str]` | Valid response options (displayed as buttons in UI) | ## Platform Configuration Access HITL configuration from: **Deployment → Settings → Human in the Loop Configuration** HITL Configuration Settings ### Email Notifications Toggle to enable or disable email notifications for HITL requests. | Setting | Default | Description | | ------------------- | ------- | -------------------------------------- | | Email Notifications | Enabled | Send emails when feedback is requested | When disabled, responders must use the dashboard UI or you must configure webhooks for custom notification systems. ### SLA Target Set a target response time for tracking and metrics purposes. | Setting | Description | | -------------------- | ----------------------------------------------------------------- | | SLA Target (minutes) | Target response time. Used for dashboard metrics and SLA tracking | Leave empty to disable SLA tracking. ## Email Notifications & Responses The HITL system uses an email-first architecture where responders can reply directly to notification emails. ### How Email Responses Work When a HITL request is created, an email is sent to the assigned responder with the review content and context. The email includes a special reply-to address with a signed token for authentication. The responder simply replies to the email with their feedback—no login required. The platform receives the reply, verifies the signed token, and matches the sender email. The feedback is recorded and the flow continues with the human's input. ### Response Format Responders can reply with: * **Emit option**: If the reply matches an `emit` option (e.g., "approved"), it's used directly * **Free-form text**: Any text response is passed to the flow as feedback * **Plain text**: The first line of the reply body is used as feedback ### Confirmation Emails After processing a reply, the responder receives a confirmation email indicating whether the feedback was successfully submitted or if an error occurred. ### Email Token Security * Tokens are cryptographically signed for security * Tokens expire after 7 days * Sender email must match the token's authorized email * Confirmation/error emails are sent after processing ## Routing Rules Route HITL requests to specific email addresses based on method patterns. HITL Routing Rules Configuration ### Rule Structure ```json theme={null} { "name": "Approvals to Finance", "match": { "method_name": "approve_*" }, "assign_to_email": "finance@company.com", "assign_from_input": "manager_email" } ``` ### Matching Patterns | Pattern | Description | Example Match | | ------------------ | -------------------- | ----------------------------------- | | `approve_*` | Wildcard (any chars) | `approve_payment`, `approve_vendor` | | `review_?` | Single char | `review_a`, `review_1` | | `validate_payment` | Exact match | `validate_payment` only | ### Assignment Priority 1. **Dynamic assignment** (`assign_from_input`): If configured, pulls email from flow state 2. **Static email** (`assign_to_email`): Falls back to configured email 3. **Deployment creator**: If no rule matches, the deployment creator's email is used ### Dynamic Assignment Example If your flow state contains `{"sales_rep_email": "alice@company.com"}`, configure: ```json theme={null} { "name": "Route to Sales Rep", "match": { "method_name": "review_*" }, "assign_from_input": "sales_rep_email" } ``` The request will be assigned to `alice@company.com` automatically. **Use Case**: Pull the assignee from your CRM, database, or previous flow step to dynamically route reviews to the right person. ## Auto-Response Automatically respond to HITL requests if no human responds within a timeout. This ensures flows don't hang indefinitely. ### Configuration | Setting | Description | | ----------------- | ------------------------------------------------ | | Enabled | Toggle to enable auto-response | | Timeout (minutes) | Time to wait before auto-responding | | Default Outcome | The response value (must match an `emit` option) | HITL Auto-Response Configuration ### Use Cases * **SLA compliance**: Ensure flows don't hang indefinitely * **Default approval**: Auto-approve low-risk requests after timeout * **Graceful degradation**: Continue with a safe default when reviewers are unavailable Use auto-response carefully. Only enable it for non-critical reviews where a default response is acceptable. ## Review Process ### Dashboard Interface The HITL review interface provides a clean, focused experience for reviewers: * **Markdown Rendering**: Rich formatting for review content with syntax highlighting * **Context Panel**: View flow state, execution history, and related information * **Feedback Input**: Provide detailed feedback and comments with your decision * **Quick Actions**: One-click emit option buttons with optional comments HITL Pending Requests List ### Response Methods Reviewers can respond via three channels: | Method | Description | | --------------- | ---------------------------------------- | | **Email Reply** | Reply directly to the notification email | | **Dashboard** | Use the Enterprise dashboard UI | | **API/Webhook** | Programmatic response via API | ### History & Audit Trail Every HITL interaction is tracked with a complete timeline: * Decision history (approve/reject/revise) * Reviewer identity and timestamp * Feedback and comments provided * Response method (email/dashboard/API) * Response time metrics ## Analytics & Monitoring Track HITL performance with comprehensive analytics. ### Performance Dashboard HITL Metrics Dashboard Monitor average and median response times by reviewer or flow. Analyze review volume patterns to optimize team capacity. View approval/rejection rates across different review types. Track percentage of reviews completed within SLA targets. ### Audit & Compliance Enterprise-ready audit capabilities for regulatory requirements: * Complete decision history with timestamps * Reviewer identity verification * Immutable audit logs * Export capabilities for compliance reporting ## Common Use Cases **Use Case**: Internal security questionnaire automation with human validation * AI generates responses to security questionnaires * Security team reviews and validates accuracy via email * Approved responses are compiled into final submission * Full audit trail for compliance **Use Case**: Marketing content requiring legal/brand review * AI generates marketing copy or social media content * Route to brand team email for voice/tone review * Automatic publishing upon approval **Use Case**: Expense reports, contract terms, budget allocations * AI pre-processes and categorizes financial requests * Route based on amount thresholds using dynamic assignment * Maintain complete audit trail for financial compliance **Use Case**: Route reviews to account owners from your CRM * Flow fetches account owner email from CRM * Store email in flow state (e.g., `account_owner_email`) * Use `assign_from_input` to route to the right person automatically **Use Case**: AI output validation before customer delivery * AI generates customer-facing content or responses * QA team reviews via email notification * Feedback loops improve AI performance over time ## Webhooks API When your Flows pause for human feedback, you can configure webhooks to send request data to your own application. This enables: * Building custom approval UIs * Integrating with internal tools (Jira, ServiceNow, custom dashboards) * Routing approvals to third-party systems * Mobile app notifications * Automated decision systems HITL Webhook Configuration ### Configuring Webhooks Go to your **Deployment** → **Settings** → **Human in the Loop** Click to expand the **Webhooks** configuration Enter your webhook URL (must be HTTPS in production) Click **Save Configuration** to activate You can configure multiple webhooks. Each active webhook receives all HITL events. ### Webhook Events Your endpoint will receive HTTP POST requests for these events: | Event Type | When Triggered | | ------------- | ----------------------------------------- | | `new_request` | A flow pauses and requests human feedback | ### Webhook Payload All webhooks receive a JSON payload with this structure: ```json theme={null} { "event": "new_request", "request": { "id": "550e8400-e29b-41d4-a716-446655440000", "flow_id": "flow_abc123", "method_name": "review_article", "message": "Please review this article for publication.", "emit_options": ["approved", "rejected", "request_changes"], "state": { "article_id": 12345, "author": "john@example.com", "category": "technology" }, "metadata": {}, "created_at": "2026-01-14T12:00:00Z" }, "deployment": { "id": 456, "name": "Content Review Flow", "organization_id": 789 }, "callback_url": "https://api.crewai.com/...", "assigned_to_email": "reviewer@company.com" } ``` ### Responding to Requests To submit feedback, **POST to the `callback_url`** included in the webhook payload. ```http theme={null} POST {callback_url} Content-Type: application/json { "feedback": "Approved. Great article!", "source": "my_custom_app" } ``` ### Security All webhook requests are cryptographically signed using HMAC-SHA256 to ensure authenticity and prevent tampering. #### Webhook Security * **HMAC-SHA256 signatures**: Every webhook includes a cryptographic signature * **Per-webhook secrets**: Each webhook has its own unique signing secret * **Encrypted at rest**: Signing secrets are encrypted in our database * **Timestamp verification**: Prevents replay attacks #### Signature Headers Each webhook request includes these headers: | Header | Description | | ------------- | -------------------------------------------- | | `X-Signature` | HMAC-SHA256 signature: `sha256=` | | `X-Timestamp` | Unix timestamp when the request was signed | #### Verification Verify by computing: ```python theme={null} import hmac import hashlib expected = hmac.new( signing_secret.encode(), f"{timestamp}.{payload}".encode(), hashlib.sha256 ).hexdigest() if hmac.compare_digest(expected, signature): # Valid signature ``` ### Error Handling Your webhook endpoint should return a 2xx status code to acknowledge receipt: | Your Response | Our Behavior | | ------------- | ------------------------------ | | 2xx | Webhook delivered successfully | | 4xx/5xx | Logged as failed, no retry | | Timeout (30s) | Logged as failed, no retry | ## Security & RBAC ### Dashboard Access HITL access is controlled at the deployment level: | Permission | Capability | | --------------------------- | ------------------------------------------- | | `manage_human_feedback` | Configure HITL settings, view all requests | | `respond_to_human_feedback` | Respond to requests, view assigned requests | ### Email Response Authorization For email replies: 1. The reply-to token encodes the authorized email 2. Sender email must match the token's email 3. Token must not be expired (7-day default) 4. Request must still be pending ### Audit Trail All HITL actions are logged: * Request creation * Assignment changes * Response submission (with source: dashboard/email/API) * Flow resume status ## Troubleshooting ### Emails Not Sending 1. Check "Email Notifications" is enabled in configuration 2. Verify routing rules match the method name 3. Verify assignee email is valid 4. Check deployment creator fallback if no routing rules match ### Email Replies Not Processing 1. Check token hasn't expired (7-day default) 2. Verify sender email matches assigned email 3. Ensure request is still pending (not already responded) ### Flow Not Resuming 1. Check request status in dashboard 2. Verify callback URL is accessible 3. Ensure deployment is still running ## Best Practices **Start Simple**: Begin with email notifications to deployment creator, then add routing rules as your workflows mature. 1. **Use Dynamic Assignment**: Pull assignee emails from your flow state for flexible routing. 2. **Configure Auto-Response**: Set up a fallback for non-critical reviews to prevent flows from hanging. 3. **Monitor Response Times**: Use analytics to identify bottlenecks and optimize your review process. 4. **Keep Review Messages Clear**: Write clear, actionable messages in the `@human_feedback` decorator. 5. **Test Email Flow**: Send test requests to verify email delivery before going to production. ## Related Resources Implementation guide for the `@human_feedback` decorator Step-by-step guide for setting up HITL workflows Configure role-based access control for your organization Set up real-time event notifications # Hallucination Guardrail Source: https://docs-platform.crewai.com/platform/en/features/hallucination-guardrail Prevent and detect AI hallucinations in your CrewAI tasks ## Overview The Hallucination Guardrail is an enterprise feature that validates AI-generated content to ensure it's grounded in facts and doesn't contain hallucinations. It analyzes task outputs against reference context and provides detailed feedback when potentially hallucinated content is detected. ## What are Hallucinations? AI hallucinations occur when language models generate content that appears plausible but is factually incorrect or not supported by the provided context. The Hallucination Guardrail helps prevent these issues by: * Comparing outputs against reference context * Evaluating faithfulness to source material * Providing detailed feedback on problematic content * Supporting custom thresholds for validation strictness ## Basic Usage ### Setting Up the Guardrail ```python theme={null} from crewai.tasks.hallucination_guardrail import HallucinationGuardrail from crewai import LLM # Basic usage - will use task's expected_output as context guardrail = HallucinationGuardrail( llm=LLM(model="gpt-4o-mini") ) # With explicit reference context context_guardrail = HallucinationGuardrail( context="AI helps with various tasks including analysis and generation.", llm=LLM(model="gpt-4o-mini") ) ``` ### Adding to Tasks ```python theme={null} from crewai import Task # Create your task with the guardrail task = Task( description="Write a summary about AI capabilities", expected_output="A factual summary based on the provided context", agent=my_agent, guardrail=guardrail # Add the guardrail to validate output ) ``` ## Advanced Configuration ### Custom Threshold Validation For stricter validation, you can set a custom faithfulness threshold (0-10 scale): ```python theme={null} # Strict guardrail requiring high faithfulness score strict_guardrail = HallucinationGuardrail( context="Quantum computing uses qubits that exist in superposition states.", llm=LLM(model="gpt-4o-mini"), threshold=8.0 # Requires score >= 8 to pass validation ) ``` ### Including Tool Response Context When your task uses tools, you can include tool responses for more accurate validation: ```python theme={null} # Guardrail with tool response context weather_guardrail = HallucinationGuardrail( context="Current weather information for the requested location", llm=LLM(model="gpt-4o-mini"), tool_response="Weather API returned: Temperature 22°C, Humidity 65%, Clear skies" ) ``` ## How It Works ### Validation Process 1. **Context Analysis**: The guardrail compares task output against the provided reference context 2. **Faithfulness Scoring**: Uses an internal evaluator to assign a faithfulness score (0-10) 3. **Verdict Determination**: Determines if content is faithful or contains hallucinations 4. **Threshold Checking**: If a custom threshold is set, validates against that score 5. **Feedback Generation**: Provides detailed reasons when validation fails ### Validation Logic * **Default Mode**: Uses verdict-based validation (FAITHFUL vs HALLUCINATED) * **Threshold Mode**: Requires faithfulness score to meet or exceed the specified threshold * **Error Handling**: Gracefully handles evaluation errors and provides informative feedback ## Guardrail Results The guardrail returns structured results indicating validation status: ```python theme={null} # Example of guardrail result structure { "valid": False, "feedback": "Content appears to be hallucinated (score: 4.2/10, verdict: HALLUCINATED). The output contains information not supported by the provided context." } ``` ### Result Properties * **valid**: Boolean indicating whether the output passed validation * **feedback**: Detailed explanation when validation fails, including: * Faithfulness score * Verdict classification * Specific reasons for failure ## Integration with Task System ### Automatic Validation When a guardrail is added to a task, it automatically validates the output before the task is marked as complete: ```python theme={null} # Task output validation flow task_output = agent.execute_task(task) validation_result = guardrail(task_output) if validation_result.valid: # Task completes successfully return task_output else: # Task fails with validation feedback raise ValidationError(validation_result.feedback) ``` ### Event Tracking The guardrail integrates with CrewAI's event system to provide observability: * **Validation Started**: When guardrail evaluation begins * **Validation Completed**: When evaluation finishes with results * **Validation Failed**: When technical errors occur during evaluation ## Best Practices ### Context Guidelines Include all relevant factual information that the AI should base its output on: ```python theme={null} context = """ Company XYZ was founded in 2020 and specializes in renewable energy solutions. They have 150 employees and generated $50M revenue in 2023. Their main products include solar panels and wind turbines. """ ``` Only include information directly related to the task to avoid confusion: ```python theme={null} # Good: Focused context context = "The current weather in New York is 18°C with light rain." # Avoid: Unrelated information context = "The weather is 18°C. The city has 8 million people. Traffic is heavy." ``` Ensure your reference context reflects current, accurate information. ### Threshold Selection Begin without custom thresholds to understand baseline performance. * **High-stakes content**: Use threshold 8-10 for maximum accuracy * **General content**: Use threshold 6-7 for balanced validation * **Creative content**: Use threshold 4-5 or default verdict-based validation Track validation results and adjust thresholds based on false positives/negatives. ## Performance Considerations ### Impact on Execution Time * **Validation Overhead**: Each guardrail adds \~1-3 seconds per task * **LLM Efficiency**: Choose efficient models for evaluation (e.g., gpt-4o-mini) ### Cost Optimization * **Model Selection**: Use smaller, efficient models for guardrail evaluation * **Context Size**: Keep reference context concise but comprehensive * **Caching**: Consider caching validation results for repeated content ## Troubleshooting **Possible Causes:** * Context is too restrictive or unrelated to task output * Threshold is set too high for the content type * Reference context contains outdated information **Solutions:** * Review and update context to match task requirements * Lower threshold or use default verdict-based validation * Ensure context is current and accurate **Possible Causes:** * Threshold too high for creative or interpretive tasks * Context doesn't cover all valid aspects of the output * Evaluation model being overly conservative **Solutions:** * Lower threshold or use default validation * Expand context to include broader acceptable content * Test with different evaluation models **Possible Causes:** * Network connectivity issues * LLM model unavailable or rate limited * Malformed task output or context **Solutions:** * Check network connectivity and LLM service status * Implement retry logic for transient failures * Validate task output format before guardrail evaluation Contact our support team for assistance with hallucination guardrail configuration or troubleshooting. # Marketplace Source: https://docs-platform.crewai.com/platform/en/features/marketplace Discover, install, and govern reusable assets for your enterprise crews. ## Overview The Marketplace provides a curated surface for discovering integrations, internal tools, and reusable assets that accelerate crew development. Marketplace Overview ## Discoverability * Browse by category and capability * Search for assets by name or keyword ## Install & Enable * One‑click install for approved assets * Enable or disable per crew as needed * Configure required environment variables and scopes Install & Configure You can also download the templates directly from the marketplace by clicking on the `Download` button so you can use them locally or refine them to your needs. ## Related Connect external apps and manage internal tools your agents can use. Publish and install tools to enhance your crews' capabilities. Store, share, and reuse agent definitions across teams and projects. # One Card per Step Source: https://docs-platform.crewai.com/platform/en/features/merged-step-card Each step on the Studio canvas is a single card that combines the task and the agent that performs it. ## Overview On the Studio canvas, each step of work is represented by a **single card**. The card combines two things that used to live in separate nodes: * **The task** — what to do (name, description, expected output, and response format). * **The agent** — who does it (the assigned agent, its model, and its tools). An agent isn't an independent participant in your workflow — it's an attribute of the task: *which agent performs this work.* Putting the task and its agent on one card makes that relationship explicit and turns your automation into a single, left-to-right chain of work units that's easier to read at a glance. Merged step cards on the canvas ## On the canvas Each collapsed card shows: * The **task name and description** at the top. * A **footer summarizing the assigned agent** — avatar, name, model, and tools. There's no separate agent node and no vertical agent → task edge. Your steps connect directly to one another in the order they run. ## In the editor Open a card to edit it. The expanded view is the same card in a detailed state — not a different screen — organized into two clearly labeled sections. Expanded step editor ### The task — what to do Open by default, since this is what you usually edit: * **Name** * **Description** * **Expected Output** * **Response Format** — surfaced here because it controls exactly what downstream steps (such as routing) read from this step. ### The agent — who does it The assigned agent is shown as a summary — **name, model, and tools inline**. Its deeper configuration is preserved behind two disclosures: * **Role, goal & backstory** * **Agent settings** — reasoning, max reasoning attempts, allow delegation, max iterations, and LLM settings. An agent's full configuration — Role, Goal, Backstory, Model, Tools, LLM Settings, and the complete Agent Settings block — lives behind the **Role, goal & backstory** and **Agent settings** disclosures, organized by how often you edit it. ## Swapping vs. editing the agent There are two distinct ways to work with the agent on a card, and they do different things: * **Swap** reassigns *which* agent performs this task. Use the **Swap** control to pick a different agent from this project, choose one from your Agent Repository, or create a new agent. This is scoped to the task. * **Editing** the agent — opening **Role, goal & backstory** or **Agent settings** — changes the agent *itself*. Swap agent panel **Agents are reusable and shared.** The same agent can perform more than one task across your project. Editing an agent's role, backstory, or settings updates that agent **everywhere it's used** — not just on the card you opened. If you want a change to apply to only one step, **Swap** in a different agent instead of editing the shared one. ## Related Build automations with AI assistance and a visual editor. Manage and reuse agents across your automations. # PII Redaction for Traces Source: https://docs-platform.crewai.com/platform/en/features/pii-trace-redactions Automatically redact sensitive data from crew and flow execution traces ## Overview PII Redaction is a CrewAI AMP feature that automatically detects and masks Personally Identifiable Information (PII) in your crew and flow execution traces. This ensures sensitive data like credit card numbers, social security numbers, email addresses, and names are not exposed in your CrewAI AMP traces. You can also create custom recognizers to protect organization-specific data. PII Redaction is available on the Enterprise plan. Deployment must be version 1.8.0 or higher. PII Redaction Overview ## Why PII Redaction Matters When running AI agents in production, sensitive information often flows through your crews: * Customer data from CRM integrations * Financial information from payment processors * Personal details from form submissions * Internal employee data Without proper redaction, this data appears in traces, making compliance with regulations like GDPR, HIPAA, and PCI-DSS challenging. PII Redaction solves this by automatically masking sensitive data before it's stored in traces. ## How It Works 1. **Detect** - Scan trace event data for known PII patterns 2. **Classify** - Identify the type of sensitive data (credit card, SSN, email, etc.) 3. **Mask/Redact** - Replace the sensitive data with masked values based on your configuration ``` Original: "Contact john.doe@company.com or call 555-123-4567" Redacted: "Contact or call " ``` ## Enabling PII Redaction You must be on the Enterprise plan and your deployment must be version 1.8.0 or higher to use this feature. In the CrewAI AMP dashboard, select your deployed crew and go to one of your deployments/automations, then navigate to **Settings** → **PII Protection**. Toggle on **PII Redaction for Traces**. This will enable automatic scanning and redaction of trace data. You need to manually enable PII Redaction for each deployment. Enable PII Redaction Select which types of PII to detect and redact. Each entity can be individually enabled or disabled. Configure Entities Save your configuration. PII redaction will be active on all subsequent crew executions, no redeployment is needed. ## Supported Entity Types CrewAI supports the following PII entity types, organized by category. ### Global Entities | Entity | Description | Example | | ----------------- | --------------------------------------------- | --------------------------------------------- | | `CREDIT_CARD` | Credit/debit card numbers | "4111-1111-1111-1111" | | `CRYPTO` | Cryptocurrency wallet addresses | "bc1qxy2kgd..." | | `DATE_TIME` | Dates and times | "January 15, 2024" | | `EMAIL_ADDRESS` | Email addresses | "[john@example.com](mailto:john@example.com)" | | `IBAN_CODE` | International bank account numbers | "DE89 3704 0044 0532 0130 00" | | `IP_ADDRESS` | IPv4 and IPv6 addresses | "192.168.1.1" | | `LOCATION` | Geographic locations | "New York City" | | `MEDICAL_LICENSE` | Medical license numbers | "MD12345" | | `NRP` | Nationalities, religious, or political groups | - | | `PERSON` | Personal names | "John Doe" | | `PHONE_NUMBER` | Phone numbers in various formats | "+1 (555) 123-4567" | | `URL` | Web URLs | "[https://example.com](https://example.com)" | ### US-Specific Entities | Entity | Description | Example | | ------------------- | --------------------------- | ------------- | | `US_BANK_NUMBER` | US Bank account numbers | "1234567890" | | `US_DRIVER_LICENSE` | US Driver's license numbers | "D1234567" | | `US_ITIN` | Individual Taxpayer ID | "900-70-0000" | | `US_PASSPORT` | US Passport numbers | "123456789" | | `US_SSN` | Social Security Numbers | "123-45-6789" | ## Redaction Actions For each enabled entity, you can configure how the data is redacted: | Action | Description | Example Output | | -------- | ---------------------------------- | --------------- | | `mask` | Replace with the entity type label | `` | | `redact` | Completely remove the text | *(empty)* | ## Custom Recognizers In addition to built-in entities, you can create **custom recognizers** to detect organization-specific PII patterns. Custom Recognizers ### Recognizer Types You have two options for custom recognizers: | Type | Best For | Example Use Case | | ------------------------- | ---------------------------------------- | ------------------------------------------------- | | **Pattern-based (Regex)** | Structured data with predictable formats | Salary amounts, employee IDs, project codes | | **Deny-list** | Exact string matches | Company names, internal codenames, specific terms | ### Creating a Custom Recognizer Go to your Organization **Settings** → **Organization** → **Add Recognizer**. Configure Recognizer Configure the following fields: * **Name**: A descriptive name for the recognizer * **Entity Type**: The entity label that will appear in redacted output (e.g., `EMPLOYEE_ID`, `SALARY`) * **Type**: Choose between Regex Pattern or Deny List * **Pattern/Values**: Regex pattern or list of strings to match * **Confidence Threshold**: Minimum score (0.0-1.0) required for a match to trigger redaction. Higher values (e.g., 0.8) reduce false positives but may miss some matches. Lower values (e.g., 0.5) catch more matches but may over-redact. Default is 0.8. * **Context Words** (optional): Words that increase detection confidence when found nearby Save the recognizer. It will be available to enable on your deployments. ### Understanding Entity Types The **Entity Type** determines how matched content appears in redacted traces: ``` Entity Type: SALARY Pattern: salary:\s*\$\s*\d+ Input: "Employee salary: $50,000" Output: "Employee " ``` ### Using Context Words Context words improve accuracy by increasing confidence when specific terms appear near the matched pattern: ``` Context Words: "project", "code", "internal" Entity Type: PROJECT_CODE Pattern: PRJ-\d{4} ``` When "project" or "code" appears near "PRJ-1234", the recognizer has higher confidence it's a true match, reducing false positives. ## Viewing Redacted Traces Once PII redaction is enabled, your traces will show redacted values in place of sensitive data: ``` Task Output: "Customer placed order #12345. Contact email: , phone: . Payment processed for card ending in ." ``` Redacted values are clearly marked with angle brackets and the entity type label (e.g., ``), making it easy to understand what data was protected while still allowing you to debug and monitor crew behavior. ## Best Practices ### Performance Considerations Each enabled entity adds processing overhead. Only enable entities relevant to your data. For custom recognizers, use specific patterns to reduce false positives and improve performance. Regex patterns are best when identifying specific patterns in the traces such as salary, employee id, project code, etc. Deny-list recognizers are best when identifying exact strings in the traces such as company names, internal codenames, etc. Context words improve accuracy by only triggering detection when surrounding text matches. ## Troubleshooting **Possible Causes:** * Entity type not enabled in configuration * Pattern doesn't match the data format * Custom recognizer has syntax errors **Solutions:** * Verify entity is enabled in Settings → Security * Test regex patterns with sample data * Check logs for configuration errors **Possible Causes:** * Overly broad entity types enabled (e.g., `DATE_TIME` catches dates everywhere) * Custom recognizer patterns are too general **Solutions:** * Disable entities that cause false positives * Make custom patterns more specific * Add context words to improve accuracy **Possible Causes:** * Too many entities enabled * NLP-based entities (`PERSON`, `LOCATION`, `NRP`) are computationally expensive as they use machine learning models **Solutions:** * Only enable entities you actually need * Consider using pattern-based alternatives where possible * Monitor trace processing times in the dashboard *** ## Practical Example: Salary Pattern Matching This example demonstrates how to create a custom recognizer to detect and mask salary information in your traces. ### Use Case Your crew processes employee or financial data that includes salary information in formats like: * `salary: $50,000` * `salary: $125,000.00` * `salary:$1,500.50` You want to automatically mask these values to protect sensitive compensation data. ### Configuration Salary Recognizer Configuration | Field | Value | | ------------------------ | ------------------------------------------- | | **Name** | `SALARY` | | **Entity Type** | `SALARY` | | **Type** | Regex Pattern | | **Regex Pattern** | `salary:\s*\$\s*\d{1,3}(,\d{3})*(\.\d{2})?` | | **Action** | Mask | | **Confidence Threshold** | `0.8` | | **Context Words** | `salary, compensation, pay, wage, income` | ### Regex Pattern Breakdown | Pattern Component | Meaning | | ----------------- | ------------------------------------------------------------ | | `salary:` | Matches the literal text "salary:" | | `\s*` | Matches zero or more whitespace characters | | `\$` | Matches the dollar sign (escaped) | | `\s*` | Matches zero or more whitespace characters after \$ | | `\d{1,3}` | Matches 1-3 digits (e.g., "1", "50", "125") | | `(,\d{3})*` | Matches comma-separated thousands (e.g., ",000", ",500,000") | | `(\.\d{2})?` | Optionally matches cents (e.g., ".00", ".50") | ### Example Results ``` Original: "Employee record shows salary: $125,000.00 annually" Redacted: "Employee record shows annually" Original: "Base salary:$50,000 with bonus potential" Redacted: "Base with bonus potential" ``` Adding context words like "salary", "compensation", "pay", "wage", and "income" helps increase detection confidence when these terms appear near the matched pattern, reducing false positives. ### Enable the Recognizer for Your Deployments Creating a custom recognizer at the organization level does not automatically enable it for your deployments. You must manually enable each recognizer for every deployment where you want it applied. After creating your custom recognizer, enable it for each deployment: Go to your deployment/automation and open **Settings** → **PII Protection**. Under **Mask Recognizers**, you'll see your organization-defined recognizers. Check the box next to the recognizers you want to enable. Enable Custom Recognizer Save your changes. The recognizer will be active on all subsequent executions for this deployment. Repeat this process for each deployment where you need the custom recognizer. This gives you granular control over which recognizers are active in different environments (e.g., development vs. production). # Role-Based Access Control (RBAC) Source: https://docs-platform.crewai.com/platform/en/features/rbac Control access to crews, tools, and data with roles, scopes, and granular permissions. ## Overview RBAC in CrewAI AMP enables secure, scalable access management through two layers: 1. **Feature permissions** — control what each role can do across the platform (manage, read, or no access) 2. **Entity-level permissions** — fine-grained access on individual automations, environment variables, LLM connections, and Git repositories RBAC overview in CrewAI AMP ## Users and Roles Each member in your CrewAI workspace is assigned a role, which determines their access across various features. You can: * Use predefined roles (Owner, Member) * Create custom roles tailored to specific permissions * Assign roles at any time through the settings panel You can configure users and roles in Settings → Roles. Go to Settings → Roles in CrewAI AMP. Use a predefined role (Owner, Member) or click Create role to define a custom one. Select users and assign the role. You can change this anytime. ### Predefined Roles | Role | Description | | :--------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Owner** | Full access to all features and settings. Cannot be restricted. | | **Member** | Read access to most features, manage access to environment variables, LLM connections, and Studio projects. Cannot modify organization or default settings. | ### Configuration summary | Area | Where to configure | Options | | :-------------------- | :--------------------------------- | :-------------------------------------- | | Users & Roles | Settings → Roles | Predefined: Owner, Member; Custom roles | | Automation visibility | Automation → Settings → Visibility | Private; Whitelist users/roles | *** ## Feature Permissions Matrix Every role has a permission level for each feature area. The three levels are: * **Manage** — full read/write access (create, edit, delete) * **Read** — view-only access * **No access** — feature is hidden/inaccessible | Feature | Owner | Member (default) | Available levels | Description | | :---------------------- | :----- | :--------------- | :------------------------ | :---------------------------------------------------- | | `usage_dashboards` | Manage | Read | Manage / Read / No access | View usage metrics and analytics | | `crews_dashboards` | Manage | Read | Manage / Read / No access | View deployment dashboards, access automation details | | `invitations` | Manage | Read | Manage / Read / No access | Invite new members to the organization | | `training_ui` | Manage | Read | Manage / Read / No access | Access training/fine-tuning interfaces | | `tools` | Manage | Read | Manage / Read / No access | Create and manage tools | | `agents` | Manage | Read | Manage / Read / No access | Create and manage agents | | `environment_variables` | Manage | Manage | Manage / No access | Create and manage environment variables | | `llm_connections` | Manage | Manage | Manage / No access | Configure LLM provider connections | | `default_settings` | Manage | No access | Manage / No access | Modify organization-wide default settings | | `organization_settings` | Manage | No access | Manage / No access | Manage billing, plans, and organization configuration | | `studio_projects` | Manage | Manage | Manage / No access | Create and edit projects in Studio | When creating a custom role, most features can be set to **Manage**, **Read**, or **No access**. However, `environment_variables`, `llm_connections`, `default_settings`, `organization_settings`, and `studio_projects` only support **Manage** or **No access** — there is no read-only option for these features. *** ## Deploying from GitHub or Zip One of the most common RBAC questions is: *"What permissions does a team member need to deploy?"* ### Deploy from GitHub To deploy an automation from a GitHub repository, a user needs: 1. **`crews_dashboards`**: at least `Read` — required to access the automations dashboard where deployments are created 2. **Git repository access** (if entity-level RBAC for Git repositories is enabled): the user's role must be granted access to the specific Git repository via entity-level permissions 3. **`studio_projects`: `Manage`** — if building the crew in Studio before deploying ### Deploy from Zip To deploy an automation from a Zip file upload, a user needs: 1. **`crews_dashboards`**: at least `Read` — required to access the automations dashboard 2. **Zip deployments enabled**: the organization must not have disabled zip deployments in organization settings ### Quick Reference: Minimum Permissions for Deployment | Action | Required feature permissions | Additional requirements | | :------------------- | :------------------------------ | :----------------------------------------------- | | Deploy from GitHub | `crews_dashboards: Read` | Git repo entity access (if Git RBAC is enabled) | | Deploy from Zip | `crews_dashboards: Read` | Zip deployments must be enabled at the org level | | Build in Studio | `studio_projects: Manage` | — | | Configure LLM keys | `llm_connections: Manage` | — | | Set environment vars | `environment_variables: Manage` | Entity-level access (if entity RBAC is enabled) | *** ## Automation‑level Access Control (Entity Permissions) In addition to organization‑wide roles, CrewAI supports fine‑grained entity-level permissions that restrict access to individual resources. ### Automation Visibility Automations support visibility settings that restrict access by user or role. This is useful for: * Keeping sensitive or experimental automations private * Managing visibility across large teams or external collaborators * Testing automations in isolated contexts Deployments can be configured as private, meaning only whitelisted users and roles will be able to interact with them. You can configure automation‑level access control in Automation → Settings → Visibility tab. Navigate to Automation → Settings → Visibility. Choose Private to restrict access. The organization owner always retains access. Add specific users and roles allowed to view, run, and access logs/metrics/settings. Save changes, then confirm that non‑whitelisted users cannot view or run the automation. ### Private visibility: access outcomes | Action | Owner | Whitelisted user/role | Not whitelisted | | :--------------------------- | :---- | :-------------------- | :-------------- | | View automation | ✓ | ✓ | ✗ | | Run automation/API | ✓ | ✓ | ✗ | | Access logs/metrics/settings | ✓ | ✓ | ✗ | The organization owner always has access. In private mode, only whitelisted users and roles can view, run, and access logs/metrics/settings. Automation Visibility settings in CrewAI AMP ### Deployment Permission Types When granting entity-level access to a specific automation, you can assign these permission types: | Permission | What it allows | | :------------------ | :------------------------------------------------- | | `run` | Execute the automation and use its API | | `traces` | View execution traces and logs | | `manage_settings` | Edit, redeploy, rollback, or delete the automation | | `human_in_the_loop` | Respond to human-in-the-loop (HITL) requests | | `full_access` | All of the above | ### Entity-level RBAC for Other Resources When entity-level RBAC is enabled, access to these resources can also be controlled per user or role: | Resource | Controlled by | Description | | :-------------------- | :-------------------------------- | :-------------------------------------------------------------- | | Environment variables | Entity RBAC feature flag | Restrict which roles/users can view or manage specific env vars | | LLM connections | Entity RBAC feature flag | Restrict access to specific LLM provider configurations | | Git repositories | Git repositories RBAC org setting | Restrict which roles/users can access specific connected repos | *** ## Common Role Patterns While CrewAI ships with Owner and Member roles, most teams benefit from creating custom roles. Here are common patterns: ### Developer Role A role for team members who build and deploy automations but don't manage organization settings. | Feature | Permission | | :---------------------- | :--------- | | `usage_dashboards` | Read | | `crews_dashboards` | Manage | | `invitations` | Read | | `training_ui` | Read | | `tools` | Manage | | `agents` | Manage | | `environment_variables` | Manage | | `llm_connections` | Manage | | `default_settings` | No access | | `organization_settings` | No access | | `studio_projects` | Manage | ### Viewer / Stakeholder Role A role for non-technical stakeholders who need to monitor automations and view results. | Feature | Permission | | :---------------------- | :--------- | | `usage_dashboards` | Read | | `crews_dashboards` | Read | | `invitations` | No access | | `training_ui` | Read | | `tools` | Read | | `agents` | Read | | `environment_variables` | No access | | `llm_connections` | No access | | `default_settings` | No access | | `organization_settings` | No access | | `studio_projects` | No access | ### Ops / Platform Admin Role A role for platform operators who manage infrastructure settings but may not build agents. | Feature | Permission | | :---------------------- | :--------- | | `usage_dashboards` | Manage | | `crews_dashboards` | Manage | | `invitations` | Manage | | `training_ui` | Read | | `tools` | Read | | `agents` | Read | | `environment_variables` | Manage | | `llm_connections` | Manage | | `default_settings` | Manage | | `organization_settings` | Read | | `studio_projects` | No access | *** Contact our support team for assistance with RBAC questions. # AWS Secrets Manager (Static Credentials) Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/aws Configure AWS Secrets Manager as a secret provider for CrewAI Platform using static access keys or AssumeRole ## Overview This guide walks you through configuring AWS Secrets Manager as a secret provider for your CrewAI Platform organization, using **static credentials** (access keys, optionally with AssumeRole). By the end, CrewAI Platform will be able to read secrets stored in your AWS account and inject them as environment variable values at runtime. This guide covers the **static credentials** path — secrets are resolved at deploy time and baked into the deployment image. Rotated values require a re-deploy. If you want rotation-aware secrets that update on every automation kickoff (no re-deploy), see [AWS Workload Identity (OIDC Federation)](/platform/en/features/secrets-manager/aws-workload-identity). This guide covers the AWS-side configuration and the credential setup in CrewAI Platform. To then reference a secret from an environment variable, see [Using the Secrets Manager](/platform/en/features/secrets-manager/usage). ## Prerequisites Before starting, make sure you have: * An AWS account with permission to create IAM users, customer-managed policies, and (optionally) IAM roles. * The AWS region where your secrets live (or will live), for example `us-east-1`. * A CrewAI Platform organization where your user has the `secret_providers: manage` permission. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). ## Choose an Authentication Method CrewAI Platform supports two ways for the platform to authenticate with AWS Secrets Manager. Pick one before you begin — the steps below differ depending on which you choose. | Method | When to use | Trade-offs | | ---------------------- | ------------------------------------------- | ---------------------------------------------------------------------- | | **Static access keys** | Getting started, single-account deployments | Simplest setup; access keys must be rotated manually | | **AssumeRole** | Cross-account, production hardening | Short-lived credentials; supports External ID; requires extra IAM role | The rest of this guide uses tabs in Steps 3–5 so you can follow the path that matches your choice. ## Step 1 — Create an IAM User Open the [IAM console](https://console.aws.amazon.com/iam/), navigate to **Users**, then click **Create user**. * Suggested name: `crewai-secrets-reader`. * Leave **Provide user access to the AWS Management Console** unchecked — this principal is used programmatically by CrewAI Platform, not by humans. * Click **Next**. On the **Set permissions** page, leave the default selection. You will attach the policy in Step 3. Click **Next**, review, and click **Create user**. For full details, see the AWS documentation: [Create an IAM user in your AWS account](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html). ## Step 2 — Create the IAM Policy CrewAI Platform needs read-only access to AWS Secrets Manager and permission to decrypt secrets via KMS. Create a customer-managed policy with the following JSON. In the IAM console, navigate to **Policies**, then click **Create policy**. Choose the **JSON** tab and replace the contents with: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Sid": "SecretsManagerRead", "Effect": "Allow", "Action": [ "secretsmanager:ListSecrets", "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret" ], "Resource": "*" }, { "Sid": "KMSDecrypt", "Effect": "Allow", "Action": [ "kms:DescribeKey", "kms:Decrypt" ], "Resource": "*" } ] } ``` Click **Next**, then on the **Review and create** page: * **Policy name:** `CrewAISecretsManagerRead` * **Description (optional):** `Read-only access to AWS Secrets Manager for CrewAI Platform` Click **Create policy**. The policy above grants `*` on `Resource` for simplicity. In production, scope the `Resource` down to the ARNs of the specific secrets CrewAI Platform should access, and scope `kms:Decrypt` to the specific KMS key ARNs that encrypt those secrets. See the [AWS guidance on least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html). ## Step 3 — Attach the Policy 1. In the IAM console, navigate to **Users** and click the user you created in Step 1. 2. On the **Permissions** tab, click **Add permissions** → **Attach policies directly**. 3. Search for `CrewAISecretsManagerRead`, select it, and click **Next**. 4. Click **Add permissions**. With AssumeRole, the policy is attached to a separate IAM **role** (not directly to the user). The user from Step 1 only needs permission to call `sts:AssumeRole` on that role. **Create the role:** 1. In the IAM console, navigate to **Roles** and click **Create role**. 2. **Trusted entity type:** AWS account. Choose **This account** (or **Another AWS account** for cross-account setups, then enter the AWS account ID hosting the IAM user from Step 1). 3. (Recommended) Check **Require external ID** and enter a value you generate yourself — this is a shared secret you will paste into CrewAI Platform in Step 5. 4. Click **Next**. 5. Attach the `CrewAISecretsManagerRead` policy. 6. Click **Next**, name the role `CrewAISecretsManagerRole`, and click **Create role**. **Allow the IAM user to assume the role:** 1. Open the role you just created and copy its **ARN**. 2. In the IAM console, navigate to **Users**, click the user from Step 1, and on the **Permissions** tab click **Add permissions** → **Create inline policy**. 3. On the **JSON** tab, paste the following (replace `ROLE_ARN_FROM_ABOVE`): ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "ROLE_ARN_FROM_ABOVE" } ] } ``` 4. Name the policy `CrewAIAssumeSecretsRole` and click **Create policy**. ## Step 4 — Get Credentials 1. In the IAM console, open the user from Step 1. 2. Click the **Security credentials** tab. 3. Under **Access keys**, click **Create access key**. 4. Select **Application running outside AWS** (or **Other**) as the use case. Click **Next**. 5. (Optional) Add a description tag. Click **Create access key**. 6. Click **Show** to reveal the secret access key, then copy both the **Access key ID** and the **Secret access key**, or click **Download .csv file**. The secret access key is shown only once. If you close this page without copying it, you will need to delete the key and create a new one. For full details, see the AWS documentation: [Manage access keys for IAM users](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html). Even with AssumeRole, CrewAI Platform still needs an access key for the IAM user — it uses those keys as the calling identity to perform the `sts:AssumeRole` call. 1. Create an access key for the user exactly as described in the **Static access keys** tab above. 2. Open the role you created in Step 3 and copy: * The **Role ARN** (from the role summary). * The **External ID** you configured (if any) — you set this yourself in Step 3, so make sure you have it on hand. ## Step 5 — Add the Credential in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `aws-prod`. * **Provider:** `AWS Secrets Manager`. * **Region:** The AWS region where your secrets live, e.g. `us-east-1`. This must match the region of the secrets you want to read. * **Access Key ID:** The value from Step 4. * **Secret Access Key:** The value from Step 4. * (Optional) Check **Set as default credential for this provider**. The default credential is used by environment variables that reference AWS secrets without specifying a credential explicitly. Leave **Role ARN** and **External ID** blank. Click **Create**. Fill the form: * **Name:** A descriptive name, e.g. `aws-prod-assumerole`. * **Provider:** `AWS Secrets Manager`. * **Region:** The AWS region where your secrets live. * **Access Key ID:** The IAM user's access key from Step 4 (used to call STS). * **Secret Access Key:** The IAM user's secret access key from Step 4. * **Role ARN:** The Role ARN you copied in Step 4. * **External ID:** The External ID you set on the role's trust policy (omit if none). * (Optional) Check **Set as default credential for this provider**. Click **Create**. **How the two modes behave at runtime:** * With **static access keys** only, CrewAI Platform calls AWS Secrets Manager directly using the keys you supplied. * When a **Role ARN** is set, CrewAI Platform first calls `sts:AssumeRole` with the supplied access keys (and External ID if configured), then uses the short-lived credentials returned by STS to read your secrets. ## Step 6 — Create at Least One Secret in AWS If you do not already have secrets in AWS Secrets Manager, create one now so you can verify the connection in Step 7. In the [AWS Secrets Manager console](https://console.aws.amazon.com/secretsmanager/), click **Store a new secret**. * **Secret type:** Choose **Other type of secret**. * **Key/value pairs** — either: * Enter one or more key/value pairs (recommended for structured secrets), or * Use the **Plaintext** tab for a single string value. * **Encryption key:** Use `aws/secretsmanager` (the AWS-managed key) unless you have a specific KMS key requirement. Click **Next**, then enter: * **Secret name:** A unique name, e.g. `crewai/openai-api-key`. * **Description (optional):** A short note about what the secret is for. Click **Next** through the rotation and review steps, then click **Store**. **JSON-key reference syntax.** If you store a secret with multiple key/value pairs (a JSON object), CrewAI Platform can extract a specific field using the `secret-name#json_key` syntax in environment variable references. For example, a secret named `database-credentials` with `{"username": "...", "password": "..."}` can be referenced as `database-credentials#password`. See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for details. For full details, see the AWS documentation: [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html). ## Step 7 — Test the Connection Back in CrewAI Platform, on the **Secret Provider Credentials** page, find the credential you just created and click **Test Connection**. A success toast confirms that CrewAI Platform can authenticate to AWS and read secrets from your account. If the test fails, check the most common causes: | Symptom | Likely cause | | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `AccessDenied` on `secretsmanager:ListSecrets` | Policy not attached, or wrong user. Re-check Step 3. | | `AccessDenied` on `kms:Decrypt` | Missing the `KMSDecrypt` statement, or your secrets use a customer-managed KMS key not covered by `Resource: "*"`. | | `InvalidClientTokenId` / `SignatureDoesNotMatch` | Wrong access key ID or secret access key. Re-check Step 4 and Step 5. | | `RegionDisabledException` / no secrets found | The credential's **Region** does not match where your secrets actually live. | | `AccessDenied` on `sts:AssumeRole` (AssumeRole only) | Inline `sts:AssumeRole` policy missing on the IAM user, or the role's trust policy does not allow this principal, or the External ID does not match. | | Test passes immediately after creating the IAM user, but fails next time | IAM credentials sometimes take a minute or two to propagate globally. Retry. | ## Next Steps Now that AWS is connected, head to [Using the Secrets Manager](/platform/en/features/secrets-manager/usage) to: * Grant org members the right permissions to use (or manage) Secrets Manager. * Reference your AWS secrets from CrewAI Platform environment variables. If you want **rotation-aware** secrets that propagate without re-deploying, switch to [AWS Workload Identity (OIDC Federation)](/platform/en/features/secrets-manager/aws-workload-identity) — same secret store, no static credentials, secrets are fetched per kickoff. # AWS Workload Identity (OIDC Federation) Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/aws-workload-identity Configure AWS Secrets Manager via Workload Identity for rotation-aware, credential-free secret access ## Overview This guide configures AWS Secrets Manager as a secret provider using **Workload Identity Federation**: CrewAI Platform mints short-lived OIDC tokens, exchanges them for AWS credentials via STS, and reads your secrets — without a long-lived AWS access key being stored anywhere. **Why this path:** secrets are resolved at automation execution time, so **rotated values propagate to the next kickoff with no re-deploy**. If you only need static credentials and don't care about rotation propagation, see the simpler [AWS — static keys / AssumeRole](/platform/en/features/secrets-manager/aws) guide. ### How it works at runtime 1. The deployment worker requests a fresh OIDC JWT from CrewAI Platform. 2. The worker calls `sts:AssumeRoleWithWebIdentity` on the IAM role you set up below, presenting the JWT. 3. AWS STS validates the JWT against CrewAI Platform's public OIDC issuer (so your platform installation must be reachable from AWS), then returns short-lived AWS credentials. 4. The worker uses those credentials to call `secretsmanager:GetSecretValue`. 5. The fetched value is injected as the environment variable's value for that automation kickoff. OIDC subject tokens are cached for \~1 hour to avoid re-issuing on every kickoff. Secret values are fetched fresh on every kickoff regardless of OIDC cache state, which is what makes this path rotation-aware. ## Prerequisites Before starting, make sure you have: * The automation pod image must include CrewAI runtime version `1.14.5` or later. * An AWS account with permission to create IAM OIDC providers, IAM roles, and IAM policies. * The AWS region where your secrets live (or will live), e.g. `us-east-1`. * A CrewAI Platform organization where your user has the `workload_identity_configs: manage` and `secret_providers: manage` permissions. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). * **Your CrewAI organization UUID.** Find it on the organization's settings page in CrewAI Platform — the trust policy in Step 3 binds the IAM role to this specific organization. * **Your CrewAI Platform installation must be reachable from AWS over HTTPS** so that AWS STS can fetch the OIDC discovery document and JWKS during token validation. Confirm with your platform administrator that the host is internet-accessible (or that AWS has network reach to it via VPC peering / equivalent). ## Step 1 — Find Your CrewAI Platform OIDC Issuer URL Your CrewAI Platform installation publishes an OpenID Connect discovery document at `https:///.well-known/openid-configuration`. The `issuer` field in that document is the URL AWS will register as a trusted OIDC provider. Open the URL in a browser (replacing `` with your actual hostname, e.g. `app.crewai.com`): ``` https:///.well-known/openid-configuration ``` You should see JSON containing: ```json theme={null} { "issuer": "https://", "jwks_uri": "https:///oauth2/jwks", ... } ``` Note the exact value of `issuer` — you'll use it in Step 3. If the URL returns 404 or 503, contact your platform administrator. The OIDC issuer requires a private signing key to be configured at install time. See the platform's installation guide for the `OIDC_PRIVATE_KEY` and `OIDC_ISSUER` configuration. ## Step 2 — Register CrewAI Platform as an IAM OIDC Identity Provider Open the [IAM → Identity providers console](https://console.aws.amazon.com/iam/home#/identity_providers) and click **Add provider**. * **Provider type:** OpenID Connect. * **Provider URL:** the `issuer` value from Step 1 (e.g. `https://app.crewai.com`). * **Audience:** `sts.amazonaws.com` Click **Add provider**. Or via CLI: ```bash theme={null} aws iam create-open-id-connect-provider \ --url "https://" \ --client-id-list "sts.amazonaws.com" \ --thumbprint-list "$(echo | openssl s_client -servername -connect :443 2>/dev/null | openssl x509 -fingerprint -noout -sha1 | cut -d= -f2 | tr -d ':')" ``` Copy the **OpenIDConnectProviderArn** from the output (or the provider's ARN from the console). You'll use it in Step 3. AWS does not actually validate the thumbprint for STS WebIdentity calls — it always re-fetches the JWKS at validation time — but the API requires the field to be present. ## Step 3 — Create the IAM Role Save as `trust-policy.json`, replacing ``, `` (the issuer host **without** `https://` or `http://`, e.g. `app.crewai.com`), and `` (from the Prerequisites): ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam:::oidc-provider/" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { ":aud": "sts.amazonaws.com", ":sub": "organization:" } } } ] } ``` Create the role: ```bash theme={null} aws iam create-role \ --role-name crewai-secrets-reader \ --assume-role-policy-document file://trust-policy.json ``` Copy the **Role Arn** from the output — that's your `aws_role_arn`. You'll paste it into CrewAI Platform in Step 6. The two conditions scope the trust precisely: `aud` restricts assumption to tokens with the AWS STS audience, and `sub` scopes federation to a specific CrewAI organization — only tokens minted for that org's automations are accepted. CrewAI Platform always sets both claims on AWS workload identity tokens. ## Step 4 — Create and attach the IAM policy for Secrets Manager + KMS access Save as `secrets-policy.json`, replacing the placeholders with your account ID, region, secret-name prefix, and the KMS key ARN(s) that encrypt those secrets: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Sid": "SecretsManagerListForUI", "Effect": "Allow", "Action": "secretsmanager:ListSecrets", "Resource": "*" }, { "Sid": "SecretsManagerRead", "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": "arn:aws:secretsmanager:::secret:-*" }, { "Sid": "KMSDecrypt", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": "arn:aws:kms:::key/" } ] } ``` `SecretsManagerListForUI` powers the **Secret Name autocomplete** in the Environment Variables form and the **Test Connection** button on the credential. `secretsmanager:ListSecrets` only accepts `Resource: "*"` — it is account-scoped at the IAM layer. Attach the policy to the role using either the CLI (inline policy, simplest) or the console UI; for environments that reuse the same permissions across many roles, use the **Managed policy** tab for a reusable, named policy. ```bash theme={null} aws iam put-role-policy \ --role-name crewai-secrets-reader \ --policy-name SecretsManagerRead \ --policy-document file://secrets-policy.json ``` This attaches the policy **inline** to the role. Inline policies are tied to the role and cannot be reused on other roles. ```bash theme={null} POLICY_ARN=$(aws iam create-policy \ --policy-name CrewAISecretsReader \ --policy-document file://secrets-policy.json \ --query 'Policy.Arn' --output text) aws iam attach-role-policy \ --role-name crewai-secrets-reader \ --policy-arn "$POLICY_ARN" ``` A managed policy is a standalone IAM resource you can attach to multiple roles. 1. Open the [IAM → Roles console](https://console.aws.amazon.com/iam/home#/roles) and select **crewai-secrets-reader**. 2. On the **Permissions** tab, click **Add permissions** → **Create inline policy**. 3. Switch to the **JSON** editor and paste the contents of `secrets-policy.json`. 4. Click **Next**, give the policy a name (e.g. `SecretsManagerRead`), and click **Create policy**. To create a reusable managed policy instead, use **IAM → Policies → Create policy** and then attach it to the role from the role's **Permissions** tab. ## Step 5 — Create at Least One Secret in AWS If you don't already have a secret to test against, create one now: ```bash theme={null} aws secretsmanager create-secret \ --region \ --name crewai-test-keyword \ --secret-string "hello from aws" ``` Or via the [AWS Secrets Manager console](https://console.aws.amazon.com/secretsmanager/) → **Store a new secret**. ## Step 6 — Add a Workload Identity Configuration in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Workload Identity** and click **Add Workload Identity Config**. Fill the form: * **Name:** A descriptive name, e.g. `aws-prod`. * **Cloud Provider:** `AWS`. * **AWS Role ARN:** the **Role Arn** from Step 3. * **AWS Region:** the region where your secrets live, e.g. `us-east-1`. * (Optional) Check **Set as default for AWS** if you'd like this WI config to be the default selected when creating an AWS-backed secret credential. Click **Create**. ## Step 7 — Add a Secret Provider Credential Bound to the WI Config Navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `aws-prod-wi`. * **Provider:** `AWS Secrets Manager`. * **Authentication Method:** `Workload Identity` (instead of static keys / AssumeRole). * **Workload Identity Configuration:** select the config you created in Step 6 (e.g. `aws-prod`). * (Optional) Check **Set as default credential for this provider**. The form will only ask for **AWS Region** under Workload Identity — the static-credential fields (Access Key ID, Secret Access Key, Role ARN, External ID) are intentionally hidden because they don't apply to this path; the role ARN comes from the linked WI config. Click **Create**. ## Step 8 — Test the Connection After saving the credential, click **Test Connection**. For workload-identity credentials this verifies the OIDC handshake: CrewAI Platform mints a JWT, exchanges it with AWS STS via `sts:AssumeRoleWithWebIdentity`, and confirms the resulting credentials can call `sts:GetCallerIdentity` against the assumed role. A green result means the federation binding is healthy. A successful Test Connection proves the trust policy, OIDC provider registration, and audience condition are all wired correctly. It does **not** prove per-secret IAM is correct — `secretsmanager:GetSecretValue` on a specific secret ARN is exercised separately when an environment variable resolves at kickoff. See [Troubleshooting](#troubleshooting) for handshake failure modes. ## Step 9 — Reference the Secret in an Environment Variable Now reference the secret on an automation, exactly as you would for any other Secrets Manager-backed env var. See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for the form fields and behavior. The only difference between WI-backed and static-keys-backed env vars is **when** the secret is read: * **WI-backed:** secret value is read fresh on every automation kickoff. * **Static-keys-backed:** secret value is read at deploy time and baked into the deployment image. ## Step 10 — Verify Rotation After the deployment is running, rotate the secret in AWS: ```bash theme={null} aws secretsmanager update-secret \ --region \ --secret-id crewai-test-keyword \ --secret-string "rotated value" ``` Trigger a new automation kickoff. The kickoff's environment will see `"rotated value"` — no re-deploy, no worker restart, no waiting on a TTL. To confirm in logs (if you have access to the worker), look for: ``` Workload identity config '' (aws): N secret(s) resolved ``` This line appears for every kickoff and indicates a fresh `GetSecretValue` call against AWS. ## Troubleshooting | Symptom | Likely cause | | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Test Connection fails with a handshake error | The `sts:AssumeRoleWithWebIdentity` call was rejected. Verify the trust policy's federated principal ARN references `oidc-provider/` (host **without** `https://` or `http://`, no trailing slash), the audience condition is exactly `sts.amazonaws.com`, the `sub` condition matches your CrewAI organization UUID, and the platform's OIDC discovery URL is reachable from AWS over the public internet. | | `InvalidIdentityToken: Couldn't retrieve verification key from your identity provider` | AWS STS can't reach your CrewAI Platform host to fetch JWKS. Confirm the host is internet-accessible from AWS, the OIDC discovery URL returns 200, and the JWKS endpoint is reachable. | | `AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity` | Trust policy mismatch. Re-check Step 3: the federated principal ARN must include `oidc-provider/` (host **without** `https://` or `http://`, no trailing slash), the audience condition must be exactly `sts.amazonaws.com`, and the `sub` condition must equal `organization:`. | | Secret Name autocomplete shows `AccessDenied: secretsmanager:ListSecrets` | The role is missing `secretsmanager:ListSecrets` with `Resource: "*"`. Add the `SecretsManagerListForUI` statement from Step 4. | | Kickoff fails to resolve a secret even though Test Connection passes | The WI binding is healthy, but resource-scoped IAM is missing on the failing secret. Audit the role's `secretsmanager:GetSecretValue` and `kms:Decrypt` permissions for that specific secret's ARN and KMS key. | | `RegionDisabledException` / no secrets found | The region in the Workload Identity Config doesn't match where the secret lives. Re-check Step 6. | | Rotated value isn't picked up on the next kickoff | Confirm the env var on the automation is referencing a Workload Identity-backed credential (not a static-keys credential). The static path bakes values into the deploy image. | ### Reference Links * AWS: [Creating OpenID Connect (OIDC) identity providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) * AWS: [Configuring a role for OpenID Connect federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_relying-party.html) * AWS: [STS:AssumeRoleWithWebIdentity API reference](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) ## Next Steps * [Use secrets in environment variables and manage permissions](/platform/en/features/secrets-manager/usage) * For multi-cloud, see also [GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity) and [Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity). # Azure Key Vault Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/azure Configure Azure Key Vault as a secret provider for CrewAI Platform, end-to-end ## Overview This guide walks you through configuring Azure Key Vault as a secret provider for your CrewAI Platform organization, using a **Microsoft Entra App Registration with a client secret**. By the end, CrewAI Platform will be able to read secrets stored in your Azure Key Vault and inject them as environment variable values at runtime. This guide covers the **static credentials** path — secrets are resolved at deploy time and baked into the deployment image. Rotated values require a re-deploy. If you want rotation-aware secrets that update on every automation kickoff, see [Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity). This guide covers the Azure-side configuration and the credential setup in CrewAI Platform. To then reference a secret from an environment variable, see [Using the Secrets Manager](/platform/en/features/secrets-manager/usage). ## Prerequisites Before starting, make sure you have: * An Azure subscription with permission to create App Registrations in Microsoft Entra and to grant role assignments on Key Vault resources. * A Key Vault using **Azure RBAC** for authorization (not the legacy access-policy model). If your vault still uses access policies, switch it to RBAC under the vault's **Access configuration** blade. * A CrewAI Platform organization where your user has the `secret_providers: manage` permission. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). ## Step 1 — Create an App Registration The App Registration is the Microsoft Entra-side identity CrewAI Platform will authenticate as. In the [Microsoft Entra portal](https://entra.microsoft.com), navigate to **App registrations** and click **New registration**. * **Name:** `crewai-secrets-reader` * **Supported account types:** `Accounts in this organizational directory only (Single tenant)`. * Leave **Redirect URI** blank. Click **Register**. Note the **Application (client) ID** and **Directory (tenant) ID** on the App's overview blade — you'll paste both into CrewAI Platform in Step 4. For full details, see the Microsoft documentation: [Register an application with the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app). ## Step 2 — Create a Client Secret On the App Registration, navigate to **Certificates & secrets** → **Client secrets** → **New client secret**. * **Description:** `crewai-platform` * **Expires:** pick a duration that matches your rotation policy (Microsoft caps this at 24 months). Click **Add**. Copy the **Value** column immediately — it can never be re-displayed once you leave the page. Client secrets are long-lived static credentials. Store the value securely (in a password manager or your own secret store) and rotate it before expiry. To eliminate static credentials entirely, use [Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity) instead. ## Step 3 — Grant the App Registration Access to Key Vault CrewAI Platform needs read access to secrets in your Key Vault. Use one of two scopes — **vault-wide** for simplicity, or **per-secret** for least privilege. In the [Key Vault console](https://portal.azure.com/#view/HubsExtension/BrowseResource/resourceType/Microsoft.KeyVault%2Fvaults), open the target vault, then navigate to **Access control (IAM)** → **Add** → **Add role assignment**. * **Role:** **Key Vault Secrets User** * **Assign access to:** User, group, or service principal * **Members:** search for and select your App Registration (`crewai-secrets-reader`). Click **Review + assign**. Or via the Azure CLI: ```bash theme={null} az role assignment create \ --assignee \ --role "Key Vault Secrets User" \ --scope $(az keyvault show --name --query id -o tsv) ``` Grant the role at the level of an individual secret. Repeat for each secret CrewAI Platform should access: ```bash theme={null} az role assignment create \ --assignee \ --role "Key Vault Secrets User" \ --scope $(az keyvault secret show --vault-name --name --query id -o tsv) ``` The **Key Vault Secrets User** role allows reading secret values but not listing all secrets in the vault. CrewAI Platform's secret-name autocomplete also calls `list` — that permission is included by the role at the vault scope, but **not** at the per-secret scope. With per-secret bindings, autocomplete won't suggest secrets; type the full secret name instead. ## Step 4 — Add the Credential in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `azure-prod`. * **Provider:** `Azure Key Vault`. * **Key Vault URL:** the vault's DNS hostname, e.g. `https://my-vault.vault.azure.net`. * **Tenant ID:** your Microsoft Entra **Directory (tenant) ID** from Step 1. * **Client ID:** your App Registration's **Application (client) ID** from Step 1. * **Client Secret:** the **Value** you copied in Step 2. * (Optional) Check **Set as default credential for this provider**. The default credential is used by environment variables that reference Azure secrets without specifying a credential explicitly. Click **Create**. ## Step 5 — Create at Least One Secret in Azure Key Vault If you don't already have secrets in Key Vault, create one now so you can verify the connection in Step 6. In the Key Vault console, navigate to **Objects** → **Secrets** → **Generate/Import**. * **Upload options:** `Manual` * **Name:** e.g. `openai-api-key` * **Secret value:** paste your secret value * Leave the rest at defaults. Click **Create**. Or via the Azure CLI: ```bash theme={null} az keyvault secret set \ --vault-name \ --name openai-api-key \ --value "sk-your-actual-key" ``` **Secret name conventions.** Azure Key Vault secret names cannot contain underscores. CrewAI Platform automatically converts underscores to hyphens when calling Azure (e.g., `db_password` is sent as `db-password`), so you can keep underscore-style env-var names — but the underlying secret in Key Vault must use hyphens. **JSON-key reference syntax.** Key Vault treats secret values as opaque strings. If your secret value happens to be a JSON object, CrewAI Platform can extract a single field using the `secret-name#json_key` syntax (e.g. `database-credentials#password`). See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for details. For full details, see the Microsoft documentation: [Set and retrieve a secret](https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-cli). ## Step 6 — Test the Connection Back in CrewAI Platform, on the **Secret Provider Credentials** page, find the credential you just created and click **Test Connection**. A success toast confirms that CrewAI Platform can authenticate to Microsoft Entra and read secrets from your vault. If the test fails, check the most common causes: | Symptom | Likely cause | | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `AADSTS7000215: Invalid client secret provided` | The pasted **Client Secret** is wrong or expired. Re-create the secret (Step 2) and update the credential. | | `AADSTS700016: Application not found in the directory` | The **Tenant ID** or **Client ID** doesn't match the App Registration. Re-check Step 4. | | `Forbidden — caller does not have permission` | The App Registration is missing the **Key Vault Secrets User** role on the vault (or per-secret). Re-check Step 3. | | `Vault not found` / DNS errors | The **Key Vault URL** is wrong, or your vault has private endpoints that block public access. Confirm the host responds to `curl https://.vault.azure.net/secrets?api-version=7.4`. | | `Forbidden — request was not authorized` (vault using legacy access policies) | The vault hasn't been switched to Azure RBAC. Under the vault's **Access configuration**, set permission model to **Azure role-based access control** and re-grant the role from Step 3. | ## Next Steps Now that Azure Key Vault is connected, head to [Using the Secrets Manager](/platform/en/features/secrets-manager/usage) to: * Grant org members the right permissions to use (or manage) Secrets Manager. * Reference your Azure secrets from CrewAI Platform environment variables. If you want **rotation-aware** secrets that propagate without re-deploying, switch to [Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity) — same vault, no client secret to rotate, secrets are fetched per kickoff. ## Screenshot Reference The placeholders above map to: * `01-register-app.png` — Azure portal "Register an application" form filled with `crewai-secrets-reader`. * `02-create-client-secret.png` — App Registration → Certificates & secrets → Client secrets, with the freshly-created secret row visible (Value column highlighted before it gets masked). * `03-grant-vault-rbac.png` — Key Vault → Access control (IAM) → Add role assignment, with **Key Vault Secrets User** picked and the App Registration selected as a member. * `04-per-secret-rbac.png` — Same panel but scoped to a single secret resource (alternative least-privilege path). * `05-amp-add-credential-form-azure.png` — CrewAI Platform "Add Secret Provider Credential" form: Provider = Azure Key Vault, all five fields populated. * `06-create-secret.png` — Azure Key Vault "Create a secret" panel with `openai-api-key` and a pasted value. * `07-test-connection-success.png` — CrewAI Platform success toast / row state after clicking **Test Connection** on the credential. # Azure Workload Identity Federation Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/azure-workload-identity Configure Azure Key Vault via Microsoft Entra Workload Identity Federation for rotation-aware, credential-free secret access ## Overview This guide configures Azure Key Vault as a secret provider using **Microsoft Entra Workload Identity Federation**: CrewAI Platform mints short-lived OIDC tokens, exchanges them for an Entra access token via the Microsoft identity platform, and reads your secrets — without any client secret being stored anywhere. **Why this path:** secrets are resolved at automation execution time, so **rotated values propagate to the next kickoff with no re-deploy**. If you only need static credentials, see the simpler [Azure Key Vault — client secret](/platform/en/features/secrets-manager/azure) guide. ### How it works at runtime 1. The deployment worker requests a fresh OIDC JWT from CrewAI Platform. 2. The worker presents the JWT to Microsoft Entra at `https://login.microsoftonline.com//oauth2/v2.0/token` as a `client_assertion` (`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`), referencing the App Registration whose **Federated Identity Credential** matches the JWT's issuer + subject. 3. Entra validates the JWT against your platform's OIDC discovery document and JWKS, then returns a short-lived access token scoped to `https://vault.azure.net/.default`. 4. The worker calls Azure Key Vault to read the secret. 5. The fetched value is injected as the environment variable's value for that automation kickoff. OIDC subject tokens are cached for \~1 hour to avoid re-issuing on every kickoff. Secret values are fetched fresh on every kickoff regardless of OIDC cache state, which is what makes this path rotation-aware. ## Prerequisites Before starting, make sure you have: * The automation pod image must include CrewAI runtime version `1.14.5` or later. * An Azure subscription and a Microsoft Entra tenant you can manage. * Permission in the tenant to create App Registrations and add Federated Identity Credentials. * A Key Vault using **Azure RBAC** for authorization (not the legacy access-policy model). * A CrewAI Platform organization where your user has the `workload_identity_configs: manage` and `secret_providers: manage` permissions. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). * **Your CrewAI Platform installation must be reachable from Microsoft Entra over HTTPS** so that Entra can fetch the OIDC discovery document and JWKS during token validation. Confirm with your platform administrator that the host is internet-accessible. ## Step 1 — Find Your CrewAI Platform OIDC Issuer URL Your CrewAI Platform installation publishes an OpenID Connect discovery document at `https:///.well-known/openid-configuration`. The `issuer` field there is the URL Microsoft Entra will register as a trusted federation issuer. Open the URL in a browser: ``` https:///.well-known/openid-configuration ``` You should see JSON containing: ```json theme={null} { "issuer": "https://", "jwks_uri": "https:///oauth2/jwks", ... } ``` Note the exact value of `issuer` — you'll use it in Step 3. If the URL returns 404 or 503, contact your platform administrator. The OIDC issuer requires a private signing key to be configured at install time. See the platform's installation guide for the `OIDC_PRIVATE_KEY` and `OIDC_ISSUER` configuration. ## Step 2 — Create an App Registration In the [Microsoft Entra portal](https://entra.microsoft.com), navigate to **App registrations** and click **New registration**. * **Name:** `crewai-secrets-reader` * **Supported account types:** `Accounts in this organizational directory only (Single tenant)`. * Leave **Redirect URI** blank. Click **Register**. Note the **Application (client) ID** and **Directory (tenant) ID** on the App's overview blade — you'll use them in Step 6. ## Step 3 — Add a Federated Identity Credential The Federated Identity Credential tells Microsoft Entra: *trust JWTs minted by this issuer, with this subject, when they're presented as a client assertion for this App Registration.* On the App Registration, navigate to **Certificates & secrets** → **Federated credentials** → **Add credential**. * **Federated credential scenario:** `Other issuer`. * **Issuer:** the CrewAI Platform issuer URL from Step 1, e.g. `https://`. * **Subject identifier:** `organization:` — exactly the value of the JWT's `sub` claim. Find your org UUID in CrewAI Platform's organization settings. This scopes federation to a specific CrewAI organization — only tokens minted for that org's automations are accepted. * **Name:** any descriptive label, e.g. `crewai-org-prod`. * **Audience:** `api://AzureADTokenExchange`. This is the fixed audience Microsoft Entra requires for federated credentials and is what CrewAI Platform sets in the JWT's `aud` claim. Click **Add**. **Per-org isolation.** The subject identifier (`organization:`) restricts the federated credential to a specific CrewAI organization's tokens. If multiple CrewAI organizations should share one App Registration, add one Federated Identity Credential per organization (each with the org's UUID). For full details, see the Microsoft documentation: [Configure a federated identity credential on an app](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust). ## Step 4 — Grant the App Registration Access to Key Vault Grant the App Registration **Key Vault Secrets User** on the target vault — the same role you'd use for the static-credentials path. Use either vault-wide (simpler) or per-secret (least privilege). ```bash theme={null} az role assignment create \ --assignee \ --role "Key Vault Secrets User" \ --scope $(az keyvault show --name --query id -o tsv) ``` Vault-wide scope grants the `secrets/list` permission that the **Secret Name autocomplete** in CrewAI Platform's env-var form depends on. Choose this tab if you want autocomplete to work. ```bash theme={null} az role assignment create \ --assignee \ --role "Key Vault Secrets User" \ --scope $(az keyvault secret show --vault-name --name --query id -o tsv) ``` Per-secret bindings disable the **Secret Name autocomplete** in CrewAI Platform's env-var form (autocomplete requires `secrets/list`, which is vault-scoped only). Type the full secret name instead. For a **vault-wide** assignment: 1. Open your Key Vault in the Azure portal. 2. Click **Access control (IAM)** → **Add** → **Add role assignment**. 3. Select role **Key Vault Secrets User** → **Next**. 4. Click **Select members**, search for the App Registration `crewai-secrets-reader`, click **Select**. 5. Click **Review + assign**. For a **per-secret** assignment, use the same flow but start from **Objects** → **Secrets** → select the secret → its own **Access control (IAM)** panel. Per-secret bindings disable autocomplete (see the Per-secret tab above). ## Step 5 — Create at Least One Secret in Key Vault If you don't already have a secret to test against, create one via the Azure CLI: ```bash theme={null} az keyvault secret set \ --vault-name \ --name openai-api-key \ --value "sk-your-actual-key" ``` Or via the Azure portal: 1. Open your Key Vault and navigate to **Objects** → **Secrets**. 2. Click **Generate/Import**. 3. **Upload options:** `Manual`. **Name:** the secret name (e.g. `openai-api-key`). **Secret value:** paste the value. 4. Click **Create**. **Secret name conventions.** Azure Key Vault secret names cannot contain underscores. CrewAI Platform automatically converts underscores to hyphens when calling Azure (e.g., `db_password` is sent as `db-password`), so you can keep underscore-style env-var names — but the underlying secret in Key Vault must use hyphens. ## Step 6 — Add a Workload Identity Configuration in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Workload Identity** and click **Add Workload Identity Config**. Fill the form: * **Name:** A descriptive name, e.g. `azure-prod`. * **Cloud Provider:** `Azure`. * **Tenant ID:** your Microsoft Entra **Directory (tenant) ID** from Step 2. * **Client ID:** your App Registration's **Application (client) ID** from Step 2. * (Optional) Check **Set as default for Azure** if you'd like this to be the default WI config selected when creating an Azure-backed secret credential. The **Audience** is fixed at `api://AzureADTokenExchange` — Microsoft Entra requires this exact audience for federated credentials, so no Audience field is shown on the form. Click **Create**. ## Step 7 — Add a Secret Provider Credential Bound to the WI Config Navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `azure-prod-wi`. * **Provider:** `Azure Key Vault`. * **Authentication Method:** `Workload Identity`. * **Workload Identity Configuration:** select the config you created in Step 6. * **Key Vault URL:** the vault's DNS hostname, e.g. `https://my-vault.vault.azure.net`. * (Optional) Check **Set as default credential for this provider**. The form will only ask for **Key Vault URL** under Workload Identity — the static-credential fields (Tenant ID, Client ID, Client Secret) are intentionally hidden because they don't apply to this path; tenant + client come from the linked WI config. Click **Create**. **One App Registration, many vaults.** The Key Vault URL lives on the credential, not the WI config. So one App Registration (and one WI config) can serve multiple Key Vaults — just create one Secret Provider Credential per vault, all linked to the same WI config. ## Step 8 — Test the Connection After saving the credential, click **Test Connection**. For workload-identity credentials this verifies the OIDC handshake: CrewAI Platform mints a JWT, presents it to Microsoft Entra as a federated `client_assertion`, and confirms Entra returns a vault-scoped access token. A green result means the federation binding is healthy. A successful Test Connection proves the Federated Identity Credential's issuer, subject, and audience all match, and that the App Registration is reachable. It does **not** prove per-secret Key Vault RBAC is correct — `getSecret` against a specific secret is exercised separately when an environment variable resolves at kickoff. See [Troubleshooting](#troubleshooting) for handshake failure modes. ## Step 9 — Reference the Secret in an Environment Variable Reference the secret on an automation, exactly as you would for any other Secrets Manager-backed env var. See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for the form fields and behavior. ## Step 10 — Verify Rotation After the deployment is running, rotate the secret in Key Vault: ```bash theme={null} az keyvault secret set \ --vault-name \ --name openai-api-key \ --value "rotated value" ``` Trigger a new automation kickoff. The kickoff's environment will see `"rotated value"` — no re-deploy, no worker restart, no TTL wait. To confirm in worker logs, look for: ``` Workload identity config '' (azure): N secret(s) resolved ``` This line appears for every kickoff and indicates a fresh `getSecret` call against Azure Key Vault. For an end-to-end fingerprint-based verification, see [Verify Rotation End-to-End](/platform/en/features/secrets-manager/verify-rotation). ## Troubleshooting | Symptom | Likely cause | | ------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Test Connection fails with a handshake error | The federated `client_assertion` was rejected by Microsoft Entra. Verify the Federated Identity Credential's **Issuer** matches the platform's `issuer` value exactly, **Subject** is `organization:` (matching the JWT's `sub` claim), **Audience** is `api://AzureADTokenExchange`, and the platform's OIDC discovery URL is reachable from Entra over the public internet. | | `AADSTS70021: No matching federated identity record found for presented assertion` | The Federated Identity Credential's **Issuer** + **Subject** + **Audience** don't all match the JWT exactly. Re-check Step 3: subject must be `organization:` (matching the JWT's `sub` claim), audience must be `api://AzureADTokenExchange`. | | `AADSTS700024: Client assertion is not within its valid time range` | The CrewAI Platform host's clock is significantly skewed from real time. Check NTP on the host. | | `AADSTS50013: Assertion failed signature validation` | Microsoft Entra couldn't verify the JWT's signature. Confirm `https:///oauth2/jwks` is reachable from the public internet and serves a valid JWKS. | | Secret Name autocomplete shows `Forbidden — does not have permission to perform action 'Microsoft.KeyVault/vaults/secrets/.../list'` | The App Registration's **Key Vault Secrets User** role is scoped to a single secret. Grant the role at the vault scope so the `list` data-plane action is allowed. See Step 4. | | Kickoff fails to resolve a secret even though Test Connection passes | The WI binding is healthy, but per-secret Key Vault RBAC is missing on the failing secret. Audit **Key Vault Secrets User** on that specific secret (or extend the role assignment to the vault scope). | | `Forbidden — request was not authorized` (vault using legacy access policies) | The vault hasn't been switched to Azure RBAC. Under the vault's **Access configuration**, set permission model to **Azure role-based access control** and re-grant the role from Step 4. | | `azure_vault_url is required for Azure secret resolution` (worker logs) | The Secret Provider Credential is missing **Key Vault URL**. Re-check Step 7. | | Rotated value isn't picked up on the next kickoff | Confirm the env var on the automation is referencing a Workload Identity-backed credential (not a static-keys credential). The static path bakes values into the deploy image. | ### Reference Links * Microsoft: [Microsoft Entra Workload Identity Federation overview](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation) * Microsoft: [Configure a federated identity credential on an app](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust) * Microsoft: [Azure Key Vault RBAC guide](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide) ## Next Steps * [Use secrets in environment variables and manage permissions](/platform/en/features/secrets-manager/usage) * For multi-cloud, the AWS-equivalent setup is at [AWS Workload Identity (OIDC Federation)](/platform/en/features/secrets-manager/aws-workload-identity) and the GCP-equivalent at [GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity). ## Screenshot Reference The placeholders above map to: * `01-register-app.png` — Azure portal "Register an application" form filled with `crewai-secrets-reader`. * `02-add-federated-credential.png` — App Registration → Certificates & secrets → Federated credentials → Add credential, with **Other issuer**, the platform issuer URL, subject `organization:`, audience `api://AzureADTokenExchange`. * `03-grant-vault-rbac.png` — Key Vault → Access control (IAM) → Add role assignment, with **Key Vault Secrets User** and the App Registration selected. * `04-per-secret-rbac.png` — Same form but at a single secret's IAM scope (alternative least-privilege path). * `05-amp-add-wi-config-azure.png` — CrewAI Platform "Add Workload Identity Config" form with Cloud Provider = Azure, Tenant ID, Client ID populated. * `06-amp-wi-list-with-azure.png` — Workload Identity list page after creation, showing rows for AWS, GCP, and the new Azure config. * `07-amp-add-credential-azure-wi.png` — "Add Secret Provider Credential" form with Provider = Azure Key Vault, Auth = Workload Identity, the WI config picked, and Key Vault URL populated. # Google Cloud Secret Manager Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/gcp Configure Google Cloud Secret Manager as a secret provider for CrewAI Platform, end-to-end ## Overview This guide walks you through configuring Google Cloud Secret Manager as a secret provider for your CrewAI Platform organization, using **service account credentials**. By the end, CrewAI Platform will be able to read secrets stored in your Google Cloud project and inject them as environment variable values at runtime. This guide covers the **static credentials** path — secrets are resolved at deploy time and baked into the deployment image. Rotated values require a re-deploy. If you want rotation-aware secrets that update on every automation kickoff, see [GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity). This guide covers the GCP-side configuration and the credential setup in CrewAI Platform. To then reference a secret from an environment variable, see [Using the Secrets Manager](/platform/en/features/secrets-manager/usage). ## Prerequisites Before starting, make sure you have: * A Google Cloud project with the **Secret Manager API** enabled. Enable it in the [APIs & Services console](https://console.cloud.google.com/apis/library/secretmanager.googleapis.com) or via `gcloud`: ```bash theme={null} gcloud services enable secretmanager.googleapis.com --project=YOUR_PROJECT_ID ``` * Permission in the project to create service accounts, grant IAM roles, and (if needed) create secrets. * A CrewAI Platform organization where your user has the `secret_providers: manage` permission. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). ## Step 1 — Create a Service Account A service account is the GCP-side identity CrewAI Platform will authenticate as. In the [IAM & Admin → Service Accounts console](https://console.cloud.google.com/iam-admin/serviceaccounts), click **Create Service Account**. * **Service account name:** `crewai-secrets-reader` * **Service account ID:** auto-fills from the name (e.g. `crewai-secrets-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com`) * **Description (optional):** "Read-only access to Secret Manager for CrewAI Platform" Click **Create and Continue**. Skip the optional grants on this screen — you'll attach the role in Step 2. Click **Done**. For full details, see the GCP documentation: [Create service accounts](https://cloud.google.com/iam/docs/service-accounts-create). ## Step 2 — Grant Secret Manager Access CrewAI Platform needs permission to list and read secrets in your project. Use one of two scopes — **project-wide** for simplicity, or **per-secret** for least privilege. In the [IAM console](https://console.cloud.google.com/iam-admin/iam), click **Grant Access** and: * **New principals:** the service account's email from Step 1. * **Role:** **Secret Manager Secret Accessor** (`roles/secretmanager.secretAccessor`). Click **Save**. Or via `gcloud`: ```bash theme={null} gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="serviceAccount:crewai-secrets-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor" ``` Grant the role only on the specific secrets CrewAI Platform should access. Repeat for each secret: ```bash theme={null} gcloud secrets add-iam-policy-binding YOUR_SECRET_NAME \ --member="serviceAccount:crewai-secrets-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor" \ --project=YOUR_PROJECT_ID ``` Or in the console: open each secret in [Secret Manager](https://console.cloud.google.com/security/secret-manager), click **Permissions** in the right panel, and grant **Secret Manager Secret Accessor** to the service account. The `roles/secretmanager.secretAccessor` role grants read-only access to secret values. CrewAI Platform also calls `secretmanager.secrets.list` for the autocomplete experience in the env-var form — that permission is included in the role at the project scope, but **not** at the per-secret scope. With per-secret bindings, autocomplete won't suggest secrets; you'll need to type the full secret name. ## Step 3 — Create a Service Account Key Open the service account from Step 1 in the [IAM & Admin → Service Accounts console](https://console.cloud.google.com/iam-admin/serviceaccounts). * Click the **Keys** tab. * Click **Add Key** → **Create new key**. * **Key type:** JSON. * Click **Create**. The browser downloads a JSON file — keep it secure; it cannot be re-downloaded. Or via `gcloud`: ```bash theme={null} gcloud iam service-accounts keys create ./crewai-secrets-reader.json \ --iam-account=crewai-secrets-reader@YOUR_PROJECT_ID.iam.gserviceaccount.com ``` The service account key is a long-lived static credential. Store it securely (in a password manager or your own secret store) and rotate it on a regular cadence. To eliminate static credentials entirely, use [GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity) instead. ## Step 4 — Add the Credential in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `gcp-prod`. * **Provider:** `Google Cloud Secret Manager`. * **Project ID:** Your GCP project ID (e.g. `my-crewai-prod`). * **Service Account JSON:** Paste the entire contents of the JSON file you downloaded in Step 3. * (Optional) Check **Set as default credential for this provider**. The default credential is used by environment variables that reference GCP secrets without specifying a credential explicitly. Click **Create**. ## Step 5 — Create at Least One Secret in GCP If you don't already have secrets in GCP Secret Manager, create one now so you can verify the connection in Step 6. In the [Secret Manager console](https://console.cloud.google.com/security/secret-manager), click **Create secret**. * **Name:** A unique name, e.g. `openai-api-key`. * **Secret value:** Either paste a raw value or upload a file. * Leave the rotation, replication, and other settings at their defaults unless you have a specific requirement. Click **Create secret**. Or via `gcloud`: ```bash theme={null} echo -n "sk-your-actual-key" | gcloud secrets create openai-api-key \ --data-file=- \ --project=YOUR_PROJECT_ID \ --replication-policy=automatic ``` **JSON-key reference syntax.** GCP Secret Manager treats secret values as opaque blobs. If your secret value happens to be a JSON string, CrewAI Platform can extract a single field using the `secret-name#json_key` syntax (e.g. `database-credentials#password`). See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for details. For full details, see the GCP documentation: [Create a secret](https://cloud.google.com/secret-manager/docs/create-secret-quickstart). ## Step 6 — Test the Connection Back in CrewAI Platform, on the **Secret Provider Credentials** page, find the credential you just created and click **Test Connection**. A success toast confirms that CrewAI Platform can authenticate to GCP and read secrets from your project. If the test fails, check the most common causes: | Symptom | Likely cause | | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `PERMISSION_DENIED` on listing secrets | Service account is missing `roles/secretmanager.secretAccessor`, or you scoped it per-secret (`list` is not granted). Re-check Step 2. | | `PERMISSION_DENIED` on `secretmanager.secrets.access` | Same as above, but for a specific secret. Confirm the service account has accessor role on the secret in question. | | `unauthorized_client` / `invalid_grant` | The pasted Service Account JSON is invalid, expired, or for a deleted service account. Re-create the key (Step 3) and re-paste. | | `Project ID does not match` | The Project ID field in CrewAI Platform doesn't match the project that owns the service account / secrets. Re-check Step 4. | | `API not enabled` | Secret Manager API isn't enabled on the project. See Prerequisites. | ## Next Steps Now that GCP is connected, head to [Using the Secrets Manager](/platform/en/features/secrets-manager/usage) to: * Grant org members the right permissions to use (or manage) Secrets Manager. * Reference your GCP secrets from CrewAI Platform environment variables. If you want **rotation-aware** secrets that propagate without re-deploying, switch to [GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity) — same secret store, no static credentials, secrets are fetched per kickoff. # GCP Workload Identity Federation Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/gcp-workload-identity Configure Google Cloud Secret Manager via Workload Identity Federation for rotation-aware, credential-free secret access ## Overview This guide configures Google Cloud Secret Manager as a secret provider using **Workload Identity Federation**: CrewAI Platform mints short-lived OIDC tokens, exchanges them for Google Cloud credentials via the Security Token Service, and reads your secrets — without a long-lived service account key being stored anywhere. **Why this path:** secrets are resolved at automation execution time, so **rotated values propagate to the next kickoff with no re-deploy**. If you only need static credentials, see the simpler [GCP — service account key](/platform/en/features/secrets-manager/gcp) guide. ### How it works at runtime 1. The deployment worker requests a fresh OIDC JWT from CrewAI Platform. 2. The worker exchanges the JWT for a federated Google credential via the [Security Token Service](https://cloud.google.com/iam/docs/reference/sts/rest), referencing the Workload Identity Pool Provider you set up below. 3. The worker calls `secretmanager.googleapis.com:accessSecretVersion` to read the secret, using the federated credential directly (the federated principal holds `roles/secretmanager.secretAccessor` — see Step 4). 4. The fetched value is injected as the environment variable's value for that automation kickoff. OIDC subject tokens are cached for \~1 hour to avoid re-issuing on every kickoff. Secret values are fetched fresh on every kickoff regardless of OIDC cache state, which is what makes this path rotation-aware. ## Prerequisites Before starting, make sure you have: * The automation pod image must include CrewAI runtime version `1.14.5` or later. * A Google Cloud project with the **Secret Manager API**, **Security Token Service API**, and **IAM Credentials API** enabled. Enable them via the console or: ```bash theme={null} gcloud services enable secretmanager.googleapis.com sts.googleapis.com iamcredentials.googleapis.com \ --project= ``` * Permission in the project to create Workload Identity Pools, IAM roles, service accounts, and (if needed) secrets. * A CrewAI Platform organization where your user has the `workload_identity_configs: manage` and `secret_providers: manage` permissions. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac). * **Your CrewAI Platform installation must be reachable from Google Cloud over HTTPS** so that GCP STS can fetch the OIDC discovery document and JWKS during token validation. Confirm with your platform administrator that the host is internet-accessible. ## Step 1 — Find Your CrewAI Platform OIDC Issuer URL Your CrewAI Platform installation publishes an OpenID Connect discovery document at `https:///.well-known/openid-configuration`. The `issuer` field there is the URL Google will register as a trusted OIDC provider. Open the URL in a browser: ``` https:///.well-known/openid-configuration ``` You should see JSON containing: ```json theme={null} { "issuer": "https://", "jwks_uri": "https:///oauth2/jwks", ... } ``` Note the exact value of `issuer` — you'll use it in Step 3. If the URL returns 404 or 503, contact your platform administrator. The OIDC issuer requires a private signing key to be configured at install time. See the platform's installation guide for the `OIDC_PRIVATE_KEY` and `OIDC_ISSUER` configuration. ## Step 2 — Create a Workload Identity Pool A Workload Identity Pool is a Google Cloud-side container for trusted external identities. You'll register CrewAI Platform as a provider inside this pool. ```bash theme={null} gcloud iam workload-identity-pools create crewai-pool \ --project= \ --location=global \ --display-name="CrewAI Platform" ``` Or in the [Workload Identity Pools console](https://console.cloud.google.com/iam-admin/workload-identity-pools), click **Create Pool**. ## Step 3 — Add CrewAI Platform as an OIDC Provider in the Pool ```bash theme={null} gcloud iam workload-identity-pools providers create-oidc crewai-provider \ --project= \ --location=global \ --workload-identity-pool=crewai-pool \ --display-name="CrewAI Platform OIDC" \ --issuer-uri="https://" \ --attribute-mapping="google.subject=assertion.sub,attribute.organization=assertion.organization_id" \ --attribute-condition="assertion.organization_id != ''" ``` The `--attribute-mapping` tells Google how to map JWT claims into Google attributes: * `google.subject` is the principal identifier — we map it to the JWT's `sub` claim, which CrewAI Platform sets to `organization:`. * `attribute.organization` is a custom attribute — we map it to the JWT's `organization_id` claim so you can reference it in IAM bindings later. The `--attribute-condition` is a defense-in-depth check that rejects tokens missing an `organization_id` claim. Get the **provider resource name** (you'll need it for the audience and IAM bindings): ```bash theme={null} gcloud iam workload-identity-pools providers describe crewai-provider \ --project= \ --location=global \ --workload-identity-pool=crewai-pool \ --format="value(name)" ``` Output looks like: ``` projects//locations/global/workloadIdentityPools/crewai-pool/providers/crewai-provider ``` This is your **Workload Identity Provider** value for CrewAI Platform in Step 6. CrewAI Platform automatically computes the OIDC audience as `//iam.googleapis.com/` when issuing tokens. ## Step 4 — Grant Secret Manager Access to the Federated Principal Bind both Secret Manager roles at project scope to the federated principal — one role enables the Secret Name autocomplete in the env-var form, the other allows reading secret values at automation kickoff. Both are required for the feature to work end-to-end. ```bash theme={null} PRINCIPAL_SET="principalSet://iam.googleapis.com/projects//locations/global/workloadIdentityPools/crewai-pool/attribute.organization/" # Required for the Secret Name autocomplete (calls secretmanager.secrets.list) gcloud projects add-iam-policy-binding \ --member="$PRINCIPAL_SET" \ --role="roles/secretmanager.viewer" # Required to read secret values at kickoff gcloud projects add-iam-policy-binding \ --member="$PRINCIPAL_SET" \ --role="roles/secretmanager.secretAccessor" ``` Replace `` with the numeric project number (`gcloud projects describe --format='value(projectNumber)'`) and `` with the UUID of the CrewAI Platform organization that should be allowed to read your secrets. You can find the org UUID in the platform UI on the organization's settings page, or via the API. This scopes federation to a specific CrewAI organization — only tokens minted for that org's automations are accepted. Or via the Google Cloud console: 1. Open **IAM & Admin** → **IAM** for your project. 2. Click **GRANT ACCESS**. 3. **New principals:** paste the full `principalSet://...attribute.organization/` string. 4. Assign role **Secret Manager Viewer** (`roles/secretmanager.viewer`). 5. Click **SAVE**. 6. Click **GRANT ACCESS** again and repeat with role **Secret Manager Secret Accessor** (`roles/secretmanager.secretAccessor`). **Per-org isolation.** The `principalSet://...attribute.organization/` pattern restricts access to a specific organization's tokens. If you have multiple CrewAI organizations sharing one Google Cloud project, repeat both bindings per-org with the correct UUID — or use a less restrictive attribute condition if isolation isn't needed. **Scoping `secretAccessor` per-secret (optional).** If you'd rather not grant `roles/secretmanager.secretAccessor` project-wide, omit the second binding above and bind per-secret instead: ```bash theme={null} gcloud secrets add-iam-policy-binding \ --member="$PRINCIPAL_SET" \ --role="roles/secretmanager.secretAccessor" \ --project= ``` Keep `roles/secretmanager.viewer` at the project scope either way — `secretmanager.secrets.list` (which the autocomplete relies on) cannot be granted per-secret. ## Step 5 — Create at Least One Secret in GCP If you don't already have a secret to test against, create one via the `gcloud` CLI: ```bash theme={null} echo -n "hello from gcp" | gcloud secrets create crewai-test-keyword \ --data-file=- \ --project= \ --replication-policy=automatic ``` Or via the [Secret Manager console](https://console.cloud.google.com/security/secret-manager): 1. Open **Secret Manager** in your GCP project. 2. Click **+ CREATE SECRET**. 3. **Name:** `crewai-test-keyword`. **Secret value:** paste your value. 4. Click **CREATE SECRET**. ## Step 6 — Add a Workload Identity Configuration in CrewAI Platform In CrewAI Platform, navigate to **Settings** → **Workload Identity** and click **Add Workload Identity Config**. Fill the form: * **Name:** A descriptive name, e.g. `gcp-prod`. * **Cloud Provider:** `GCP`. * **Workload Identity Provider:** the provider resource name from Step 3, e.g. `projects//locations/global/workloadIdentityPools/crewai-pool/providers/crewai-provider`. * (Optional) Toggle **Default Configuration** if you'd like this to be the default WI config selected when creating a GCP-backed secret credential. Click **Create**. ## Step 7 — Add a Secret Provider Credential Bound to the WI Config Navigate to **Settings** → **Secret Provider Credentials** and click **Add Credential**. Fill the form: * **Name:** A descriptive name, e.g. `gcp-prod-wi`. * **Provider:** `Google Cloud Secret Manager`. * **Authentication Method:** `Workload Identity`. * **Workload Identity Configuration:** select the config you created in Step 6. * **Project ID:** your GCP project ID (the same project that owns the secrets). * (Optional) Check **Set as default credential for this provider**. The form will only ask for **Project ID** under Workload Identity — the **Service Account JSON** field is intentionally hidden because it doesn't apply to this path; the federated identity comes from the linked WI config. Click **Create**. ## Step 8 — Test the Connection After saving the credential, click **Test Connection**. For workload-identity credentials this verifies the OIDC handshake: CrewAI Platform mints a JWT and exchanges it via the Security Token Service for a federated Google access token. A green result means the federation binding is healthy. A successful Test Connection proves the Workload Identity Pool, OIDC provider, attribute mapping, and attribute condition are all wired correctly. It does **not** prove Secret Manager IAM is correct — `secretmanager.secrets.list` and `secretmanager.versions.access` are exercised separately when the Secret Name autocomplete loads or when an environment variable resolves at kickoff. See [Troubleshooting](#troubleshooting) for handshake failure modes. ## Step 9 — Reference the Secret in an Environment Variable Reference the secret on an automation, exactly as you would for any other Secrets Manager-backed env var. See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for the form fields and behavior. ## Step 10 — Verify Rotation After the deployment is running, rotate the secret in GCP by adding a new version (Secret Manager always reads the latest enabled version by default): ```bash theme={null} echo -n "rotated value" | gcloud secrets versions add crewai-test-keyword \ --data-file=- \ --project= ``` Trigger a new automation kickoff. The kickoff's environment will see `"rotated value"` — no re-deploy, no worker restart, no TTL wait. To confirm in worker logs, look for: ``` Workload identity config '' (gcp): N secret(s) resolved ``` This line appears for every kickoff and indicates a fresh `accessSecretVersion` call against GCP. ## Troubleshooting | Symptom | Likely cause | | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Test Connection fails with a handshake error | The STS token exchange was rejected. Verify the Workload Identity Pool exists, the OIDC provider's issuer matches the platform's `issuer` value, and the attribute condition accepts the JWT's claims. Confirm the platform's OIDC discovery URL is reachable from GCP over the public internet. | | `Could not refresh access token: invalid_target` | The audience claim doesn't match the Workload Identity Provider's expected audience. CrewAI Platform sets the audience automatically; if you customized it, ensure it matches `//iam.googleapis.com/`. | | `Failed to fetch JWKS from issuer` | GCP STS can't reach your CrewAI Platform host. Confirm the host is internet-accessible and `/.well-known/openid-configuration` returns 200. | | `Attribute condition rejected token` | The OIDC provider's attribute condition (Step 3) requires `organization_id`. CrewAI Platform always sets this claim, so this usually means a misconfigured pool/provider. Re-check the provider's attribute condition. | | Secret Name autocomplete shows `PERMISSION_DENIED: secretmanager.secrets.list` | The federated principal is missing `roles/secretmanager.viewer` at project scope. The `secretmanager.secrets.list` permission is project-scoped only and cannot be granted per-secret. See Step 4. | | Kickoff fails to resolve a secret even though Test Connection passes | The WI binding is healthy, but `secretmanager.versions.access` is missing on the failing secret. Audit `roles/secretmanager.secretAccessor` (project-scoped, or per-secret if you scoped it that way in Step 4). | | Rotated value isn't picked up on the next kickoff | Confirm the env var on the automation is referencing a Workload Identity-backed credential (not a static-keys credential). The static path bakes values into the deploy image. | ### Reference Links * GCP: [Workload Identity Federation overview](https://cloud.google.com/iam/docs/workload-identity-federation) * GCP: [Configure Workload Identity Federation with OIDC](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers) * GCP: [Secret Manager IAM roles](https://cloud.google.com/secret-manager/docs/access-control) ## Next Steps * [Use secrets in environment variables and manage permissions](/platform/en/features/secrets-manager/usage) * For multi-cloud, see also [AWS Workload Identity (OIDC Federation)](/platform/en/features/secrets-manager/aws-workload-identity) and [Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity). # Secrets Manager Overview Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/overview Connect external secret stores to CrewAI Platform and reference managed secrets from environment variables ## Overview The Secrets Manager feature lets your organization connect an external secret store — AWS Secrets Manager, Google Cloud Secret Manager, or Azure Key Vault — and reference those secrets directly from environment variables on your automations and crews. Instead of pasting plaintext values into the platform, you store one set of credentials per provider and refer to secrets by name. This gives you: * **Centralized storage** — manage secrets in your provider rather than editing CrewAI Platform configuration. CrewAI Platform keeps no plaintext copy of the secret value. * **Reduced exposure** — sensitive values never live in plaintext in your CrewAI Platform configuration. * **Cloud-native auditability** — your provider's audit log records every secret read. Secrets Manager (both the static-credentials and Workload Identity paths) requires CrewAI runtime version `1.14.5` or later in the automation pod image. ## Two Paths: Static Credentials vs Workload Identity There are two ways to wire CrewAI Platform up to your cloud's secret store. **They differ significantly in rotation behavior**, so choose based on how often your secrets rotate and how strict your security posture is. | Aspect | Static Credentials | Workload Identity (OIDC Federation) | | ------------------------ | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | **Authentication** | Long-lived access keys / service account JSON stored in CrewAI Platform | Short-lived tokens minted per worker process; no static credentials stored anywhere | | **Rotation propagation** | Resolved at deploy time and **baked into the deployment's container image** — rotated values require a re-deploy | Resolved at **automation execution time** — rotated values propagate to the next kickoff with no re-deploy | | **Setup effort** | Lower — paste keys / upload service account JSON | Higher — register CrewAI Platform as an OIDC provider in your cloud, configure trust policies | | **Best for** | Getting started, infrequently-rotated secrets, single-account deployments | Production, frequently-rotated secrets, compliance-driven environments that prohibit long-lived credentials | **Both paths use the same UI flow** to reference secrets in environment variables (see [Using the Secrets Manager](/platform/en/features/secrets-manager/usage)). The difference is entirely in how the platform authenticates to your cloud and when it reads the secret value. ### Choose your setup guide | Provider | Static Credentials | Workload Identity | | --------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | AWS Secrets Manager | [AWS — static keys / AssumeRole](/platform/en/features/secrets-manager/aws) | [AWS — Workload Identity (OIDC)](/platform/en/features/secrets-manager/aws-workload-identity) | | Google Cloud Secret Manager | [GCP — service account key](/platform/en/features/secrets-manager/gcp) | [GCP — Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity) | | Azure Key Vault | [Azure — client secret](/platform/en/features/secrets-manager/azure) | [Azure — Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity) | The Secrets Manager and Workload Identity UIs are currently labeled **Beta** in CrewAI Platform. ## How It Fits Together Setting up Secrets Manager is a three-step flow that involves both your cloud provider and CrewAI Platform: 1. **An admin configures a provider credential.** This is the cloud-side work — and the work differs depending on which path (static credentials or Workload Identity) you choose. Provider-specific guides cover this end to end. 2. **An admin (or a permitted member) references a secret in an environment variable.** From the Environment Variables page, the user picks a provider credential and selects the secret name. See [Using the Secrets Manager](/platform/en/features/secrets-manager/usage#referencing-secrets-in-environment-variables). 3. **The automation receives the resolved value at runtime.** When a crew or automation runs, CrewAI Platform fetches the secret from your provider and injects it as the environment variable's value. With Workload Identity, this fetch happens on every kickoff (rotation-aware). With static credentials, this fetch happens at deploy time and the value is baked into the deployment image. ## Visibility & Scope WI-backed environment variables follow the same assignment model as plaintext environment variables: an automation resolves only the WI-backed variables explicitly assigned to it. Assign a WI-backed variable to an automation from the Environment Variables page on that automation; variables defined at the organization level or in a Studio project are not resolved at kickoff until you assign them. The secret-fetch stage runs on every kickoff but only does work when WI-backed environment variables are assigned to the deployment. For each assigned variable, the runtime resolves the value from your cloud provider on every crew, flow, training, test, or checkpoint-restore kickoff and writes it into the process environment. With nothing assigned, the stage is a no-op. Otherwise, cost is proportional to the number of assigned variables: a small added latency per kickoff plus one cloud-side audit-log entry per variable. At the Workload Identity *configuration* level, scope is still organization-wide today. Every automation in the organization is bootstrapped against every Workload Identity configuration the org has registered, and you cannot today bind a specific Workload Identity configuration to a specific automation. Per-automation Workload Identity scoping is on the roadmap. Until then, only register Workload Identity configurations every automation in your organization is allowed to use. ## Permissions Two CrewAI Platform features control access to Secrets Manager: * `secret_providers` — controls who can view or manage provider credentials. * `environment_variables` — controls who can create and edit environment variables (including those that reference secrets). A third feature controls Workload Identity setup: * `workload_identity_configs` — controls who can view or manage Workload Identity configurations. Required only if you're using the Workload Identity path. Owners always have full access. Members do **not** receive access to `secret_providers` or `workload_identity_configs` by default and must be granted permission via a custom role. See [Permissions (RBAC)](/platform/en/features/secrets-manager/usage#permissions-rbac) for the full matrix and step-by-step instructions. ## Next Steps Pick your path: * **Static credentials** (simpler, requires re-deploy on rotation): * [Configure AWS Secrets Manager](/platform/en/features/secrets-manager/aws) * [Configure Google Cloud Secret Manager](/platform/en/features/secrets-manager/gcp) * [Configure Azure Key Vault](/platform/en/features/secrets-manager/azure) * **Workload Identity** (rotation-aware, no re-deploy): * [Configure AWS Workload Identity](/platform/en/features/secrets-manager/aws-workload-identity) * [Configure GCP Workload Identity Federation](/platform/en/features/secrets-manager/gcp-workload-identity) * [Configure Azure Workload Identity Federation](/platform/en/features/secrets-manager/azure-workload-identity) * Then: [Use secrets in environment variables and manage permissions](/platform/en/features/secrets-manager/usage) # Using the Secrets Manager Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/usage Manage permissions and reference managed secrets from environment variables in CrewAI Platform ## Overview This guide is provider-agnostic. It assumes you (or another admin) have already configured at least one Secret Provider Credential. Pick your setup guide based on the path you want: * Static credentials: [AWS](/platform/en/features/secrets-manager/aws) · [GCP](/platform/en/features/secrets-manager/gcp) * Workload Identity (rotation-aware): [AWS](/platform/en/features/secrets-manager/aws-workload-identity) · [GCP](/platform/en/features/secrets-manager/gcp-workload-identity) Use this guide to: * Grant the right permissions to org members. * Reference secrets from environment variables on your automations. * Verify everything resolves correctly at runtime. ## Permissions (RBAC) Three CrewAI Platform features are relevant when working with Secrets Manager: * `secret_providers` — controls access to the **Secret Provider Credentials** page. * `workload_identity_configs` — controls access to the **Workload Identity** page (only relevant if you use the WI path). * `environment_variables` — controls who can create or edit environment variables. Each feature has two action levels: `read` and `manage`. Granting `manage` automatically implies `read`. ### What to Grant | Goal | `secret_providers` | `workload_identity_configs` | `environment_variables` | | ------------------------------------------------------------------------------------ | ------------------ | --------------------------- | ----------------------- | | Use existing static credentials in environment variables (no provider edits) | `read` | — | `manage` | | Create, edit, or delete static credentials | `manage` | — | `manage` | | Use existing Workload Identity-backed credentials in env vars | `read` | — | `manage` | | Create, edit, or delete Workload Identity configs (and credentials referencing them) | `manage` | `manage` | `manage` | **Owners** automatically have full access to every feature. The default **Member** role intentionally excludes `secret_providers` and `workload_identity_configs` — admins must explicitly opt members in via a custom role. ### How to Assign 1. In CrewAI Platform, navigate to **Settings** → **Roles**. From this page you can create new roles, edit each role's permissions, and assign roles to existing members of the organization. 2. Click **Create Role** to make a new role, or open an existing role to edit its permissions. 3. In the role's permission editor, toggle the relevant features per the table above: * `secret_providers`: choose **read** if this role only needs to use existing credentials, or **manage** if it should also be able to create, edit, and delete credentials. * `environment_variables`: choose **manage** so the role can create environment variables that reference secrets. 4. Save the role. 5. Assign the role to the relevant members from the same Roles page (or the org Members list). ## Referencing Secrets in Environment Variables Once a provider credential exists and your role has the right permissions, you can reference managed secrets from any environment variable. In CrewAI Platform, navigate to **Environment Variables** and click **Add Environment Variables**. Fill the form: * **Key** — the name of the environment variable. Must start with a letter or underscore and contain only letters, numbers, and underscores. Conventionally uppercase, e.g. `OPENAI_API_KEY`. * **Value Source** — choose where the value comes from: * **Direct Value** — a plaintext value you type in. Use this when you do not want to involve a provider. * **Use AWS default** (or the equivalent for your provider) — uses the credential currently marked as the default for that provider type. * **A specific named credential** — select the credential by name. Use this if you have multiple credentials for the same provider (for example, `aws-prod` and `aws-staging`) and want to pick one explicitly. * **Secret Name** — the name of the secret in your provider. Once a credential is selected, this field offers autocomplete: start typing and CrewAI Platform queries your provider for matching secret names. Use the `secret-name#json_key` syntax to extract a single field from a structured (JSON) secret. For example, given a secret `database-credentials` with value `{"username": "...", "password": "..."}`, reference `database-credentials#password` to inject just the password. **Azure Key Vault note:** Azure secret names cannot contain underscores. CrewAI Platform automatically converts underscores in your `Secret Name` field to hyphens when calling Azure (e.g., `db_password` is sent as `db-password`). Click **Create** to save the variable. When editing an existing environment variable, leaving the **Value** field blank preserves the current value. This is intentional — it lets you change other fields (like the secret name or credential) without re-entering the value. ## Verifying It Works To verify end-to-end: 1. Reference the environment variable on an automation, crew, or deployment exactly as you would any other environment variable. 2. Deploy the automation. 3. Trigger a run and confirm it completes successfully. ### Rotation behavior depends on the credential path | Credential path | When the secret is read | What rotation requires | | ------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------ | | **Static credentials** (AWS access keys, GCP service account JSON) | At **deploy time** — value is baked into the deployment image | Re-deploy the automation after rotating the secret | | **Workload Identity** (OIDC federation, AWS or GCP) | At **every automation kickoff** — value is fetched fresh from your cloud | Nothing — the next kickoff after rotation sees the new value | **If you need rotation-aware secrets** (no re-deploy on rotation), use the Workload Identity path: [AWS WI](/platform/en/features/secrets-manager/aws-workload-identity) or [GCP WI](/platform/en/features/secrets-manager/gcp-workload-identity). The trade-off is more setup effort up front (registering CrewAI Platform as an OIDC provider in your cloud) but simpler operations long-term. If the deploy or run fails with an error related to your secret, check the most common causes: | Symptom | Likely cause | | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `no credential found` | The environment variable references a provider but no specific credential was selected, and there is no default credential set for that provider type. Either select a credential explicitly on the variable, or mark a credential as default on the **Secret Provider Credentials** page. | | `secret not found` | Typo in the **Secret Name**, or the secret does not exist in the provider account/region the credential points to. Re-check both. | | Automation runs with the old value after rotating (static-credentials path) | The previous value is baked into the deployment's container image. Re-deploy the automation to pick up the rotated value. To avoid this entirely, switch the credential to the Workload Identity path. | | Automation runs with the old value after rotating (Workload Identity path) | Confirm the env var references a WI-backed credential (not a static-keys one). With WI, the next kickoff after rotation should see the new value. If it doesn't, check that the secret was actually updated in your cloud (e.g., `aws secretsmanager get-secret-value`). | | `JSON key not found` | When using `secret-name#json_key`, the underlying secret must be a valid JSON object containing that key. Verify by reading the secret directly in your provider. | ## Next Steps * [Back to the Secrets Manager overview](/platform/en/features/secrets-manager/overview) * Static credentials: [AWS](/platform/en/features/secrets-manager/aws) · [GCP](/platform/en/features/secrets-manager/gcp) * Workload Identity (rotation-aware): [AWS](/platform/en/features/secrets-manager/aws-workload-identity) · [GCP](/platform/en/features/secrets-manager/gcp-workload-identity) # Verify Rotation Source: https://docs-platform.crewai.com/platform/en/features/secrets-manager/verify-rotation A self-contained example crew that proves secret rotation propagates to running deployments without re-deploy. ## Overview This guide shows you how to verify that **a secret rotated in your cloud provider is picked up on the very next automation kickoff** — no re-deploy, no worker restart. It's only relevant when you've configured a Workload Identity-backed credential ([AWS](/platform/en/features/secrets-manager/aws-workload-identity), [GCP](/platform/en/features/secrets-manager/gcp-workload-identity), [Azure](/platform/en/features/secrets-manager/azure-workload-identity)). Static-credential deployments require a re-deploy after rotation; nothing to verify here. The recipe below uses a tiny, self-contained crew with one tool, one agent, one task. The crew prompt never references the secret value — instead, a tool reads it from `os.environ` and reports a SHA-256 fingerprint of what it sees. Rotate the secret in your cloud provider, kickoff again, and the fingerprint changes. Why a fingerprint, not the raw value? Putting raw secrets into LLM output and trace logs is a leak vector. The fingerprint is enough to confirm "the value changed" without writing the actual value anywhere observable. ## Prerequisites Before running this verification: * A WI-backed Secret Provider Credential is configured ([AWS](/platform/en/features/secrets-manager/aws-workload-identity), [GCP](/platform/en/features/secrets-manager/gcp-workload-identity), [Azure](/platform/en/features/secrets-manager/azure-workload-identity)). * An environment variable on your deployment with `Secret = true`, key `API_KEY` (or whatever name you prefer — adjust the tool below to match), referencing a secret in your cloud provider. * A way to update the secret value in your cloud provider (CLI access or the cloud console). * A way to kickoff the deployment via HTTP (curl, Postman, or the **Run** tab in CrewAI Platform). ## Step 1 — Scaffold a Verification Crew Create a classic crew project because this example wires a Python tool through `crew.py`: ```bash theme={null} crewai create crew rotation_verifier --classic --skip_provider cd rotation_verifier ``` ## Step 2 — Add the Credential Echo Tool Replace `src/rotation_verifier/tools/custom_tool.py` with a tool that reads the secret-backed env var and returns a fingerprint: ```python src/rotation_verifier/tools/credential_echo_tool.py theme={null} """Tool that verifies a runtime-injected secret without leaking the value. Reads the secret-backed env var (populated by the workload-identity secrets manager at kickoff time) and returns a stable fingerprint. Never echo raw credential values into LLM output or logs in production code — the fingerprint alone is sufficient to confirm rotation worked. """ from __future__ import annotations import hashlib import os from crewai.tools import BaseTool # Match the deployment environment variable's `key` field. ENV_VAR_NAME = "API_KEY" class CredentialEchoTool(BaseTool): name: str = "credential_echo" description: str = ( "Read the API credential from the worker's environment and return a " "fingerprint summary. Use this exactly once when asked to verify the " "current credential. Takes no arguments." ) def _run(self) -> str: value = os.environ.get(ENV_VAR_NAME) if not value: return ( f"ERROR: {ENV_VAR_NAME} env var is not set. The workload-" "identity secret fetch did not run, or the deployment is " "missing the secret-backed env var." ) fingerprint = hashlib.sha256(value.encode()).hexdigest()[:12] return f"Authenticated. credential.fingerprint=sha256:{fingerprint}" ``` ## Step 3 — Replace the Default Agent and Task Configs The crew has one agent and one task — both with descriptions that **never** mention the secret value, so task keys stay stable across rotations. ```yaml src/rotation_verifier/config/agents.yaml theme={null} credential_checker: role: > Credential Verifier goal: > Confirm that the workload-identity-backed secret reached this worker process and report a fingerprint of the current value. backstory: > You are a no-nonsense reliability engineer responsible for verifying that secrets fetched at runtime via workload identity are present and fresh. You always use the credential_echo tool exactly once and report the result verbatim — you never make up values. ``` ```yaml src/rotation_verifier/config/tasks.yaml theme={null} verify_credential_task: description: > Use the credential_echo tool to read the runtime-injected credential and produce a one-line confirmation. The current year is {current_year} (use it only in the timestamp; do not transform the credential output). expected_output: > A single line in the form: "[{current_year}] " agent: credential_checker ``` ## Step 4 — Wire the Crew Class ```python src/rotation_verifier/crew.py theme={null} from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai.agents.agent_builder.base_agent import BaseAgent from rotation_verifier.tools.credential_echo_tool import CredentialEchoTool @CrewBase class RotationVerifierCrew(): """Single-task crew that verifies a workload-identity-backed secret was successfully fetched at runtime. Rotate the underlying secret in the cloud provider, kickoff again, and the credential fingerprint in the agent's report changes — without any re-deploy, worker restart, or input change. The crew prompt itself never references the secret value. """ agents: list[BaseAgent] tasks: list[Task] @agent def credential_checker(self) -> Agent: return Agent( config=self.agents_config["credential_checker"], tools=[CredentialEchoTool()], verbose=True, ) @task def verify_credential_task(self) -> Task: return Task(config=self.tasks_config["verify_credential_task"]) @crew def crew(self) -> Crew: return Crew( agents=self.agents, tasks=self.tasks, process=Process.sequential, verbose=True, ) ``` ## Step 5 — Deploy and Configure the Secret Env Var Deploy this crew to CrewAI Platform exactly as you would any other crew. Then on the deployment's **Environment Variables** page: * **Key:** `API_KEY` (must match `ENV_VAR_NAME` in the tool) * **Value Source:** the WI-backed credential you set up in [AWS WI](/platform/en/features/secrets-manager/aws-workload-identity) or [GCP WI](/platform/en/features/secrets-manager/gcp-workload-identity) * **Secret Name:** the name of the secret in your cloud provider's Secret Manager ## Step 6 — Run the First Kickoff Replace `` and `` with values from your deployment's **Run** tab. ```bash theme={null} curl -m 60 \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -X POST https:///kickoff \ -d '{"inputs":{"current_year":"2026"}}' ``` When the kickoff completes (a few seconds), check the agent's output. You'll see: ``` [2026] Authenticated. credential.fingerprint=sha256:004421b993c9 ``` Note the fingerprint. That hash is uniquely tied to whatever secret value is currently in your cloud provider. ## Step 7 — Rotate the Secret in Your Cloud Provider ```bash theme={null} aws secretsmanager update-secret \ --region \ --secret-id \ --secret-string "rotated value" ``` Add a new version (Secret Manager always reads `latest`): ```bash theme={null} echo -n "rotated value" | gcloud secrets versions add \ --data-file=- \ --project= ``` ```bash theme={null} az keyvault secret set \ --vault-name \ --name \ --value "rotated value" ``` ## Step 8 — Run a Second Kickoff and Compare ```bash theme={null} curl -m 60 \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -X POST https:///kickoff \ -d '{"inputs":{"current_year":"2026"}}' ``` The agent's output now shows a **different fingerprint**: ``` [2026] Authenticated. credential.fingerprint=sha256:e2fc89848f72 ``` This proves the rotation was picked up by the running deployment with no re-deploy, worker restart, or other operator action. ## What This Verifies — and What It Doesn't **Verifies:** * WI OIDC token minting from CrewAI Platform works. * Cloud-side trust (IAM OIDC provider for AWS, Workload Identity Pool for GCP, Federated Identity Credential for Azure) accepts the token. * The cloud-side identity (IAM Role / GCP service account / Entra App Registration) has access to read the secret. * The secret value reaches `os.environ` of the worker process at kickoff time. * Subsequent rotations propagate to the next kickoff. **Does not verify:** * That your real production crews handle the rotation gracefully — e.g., long-running tasks that read the env var once at startup will keep using the old value until the task ends. Plan accordingly: read secrets at the point of use, not at module import. ## Why Not Reference the Secret Directly in the Prompt? A simpler-looking demo would put the secret value directly into a task description (e.g., "Research about `{api_key}`") and inspect the prompt. **Don't do that.** Two reasons: 1. **It leaks the secret into LLM call traces and provider-side logs.** Anyone with trace access can read it. 2. **It changes the task's description at every kickoff.** CrewAI Platform identifies tasks by an MD5 hash of the description; a rotating value means the hash changes per kickoff, which breaks the deploy-time → runtime task mapping. Symptom: the task records show as `pending_run` indefinitely, or only some of a multi-task crew's tasks register. The tool-based pattern in this guide sidesteps both issues: the prompt is static, the tool reads the env var at runtime, and only a fingerprint of the value reaches the LLM. ## Next Steps * [Back to the Secrets Manager overview](/platform/en/features/secrets-manager/overview) * Once verified, drop the verification crew. Real crews should follow the same pattern: secrets accessed via `os.environ` inside a tool, never substituted into prompts. # Single Sign-On (SSO) Source: https://docs-platform.crewai.com/platform/en/features/sso Configure enterprise SSO authentication for CrewAI Platform — SaaS and Factory ## Overview CrewAI Platform supports enterprise Single Sign-On (SSO) across both **SaaS (AMP)** and **Factory (self-hosted)** deployments. SSO enables your team to authenticate using your organization's existing identity provider, enforcing centralized access control, MFA policies, and user lifecycle management. ### Supported Providers | Provider | SaaS | Factory | Protocol | CLI Support | | --------------------------------- | -------------- | ------- | -------------------- | ----------- | | **WorkOS** | ✅ (default) | ✅ | OAuth 2.0 / OIDC | ✅ | | **Microsoft Entra ID** (Azure AD) | ✅ (enterprise) | ✅ | OAuth 2.0 / SAML 2.0 | ✅ | | **Okta** | ✅ (enterprise) | ✅ | OAuth 2.0 / OIDC | ✅ | | **Auth0** | ✅ (enterprise) | ✅ | OAuth 2.0 / OIDC | ✅ | | **Keycloak** | — | ✅ | OAuth 2.0 / OIDC | ✅ | ### Key Capabilities * **SAML 2.0 and OAuth 2.0 / OIDC** protocol support * **Device Authorization Grant** flow for CLI authentication * **Role-Based Access Control (RBAC)** with custom roles and per-resource permissions * **MFA enforcement** delegated to your identity provider * **User provisioning** through IdP assignment (users/groups) *** ## SaaS SSO ### Default Authentication CrewAI's managed SaaS platform (AMP) uses **WorkOS** as the default authentication provider. When you sign up at [app.crewai.com](https://app.crewai.com), authentication is handled through `login.crewai.com` — no additional SSO configuration is required. ### Enterprise Custom SSO Enterprise SaaS customers can configure SSO with their own identity provider (Entra ID, Okta, Auth0). Contact your CrewAI account team to enable custom SSO for your organization. Once configured: 1. Your team members authenticate through your organization's IdP 2. Access control and MFA policies are enforced by your IdP 3. The CrewAI CLI automatically detects your SSO configuration via `crewai enterprise configure` ### CLI Defaults (SaaS) | Setting | Default Value | | --------------------- | ------------------------ | | `enterprise_base_url` | `https://app.crewai.com` | | `oauth2_provider` | `workos` | | `oauth2_domain` | `login.crewai.com` | *** ## Factory SSO Setup Factory (self-hosted) deployments require you to configure SSO by setting environment variables in your Helm `values.yaml` and registering an application in your identity provider. ### Microsoft Entra ID (Azure AD) 1. Go to [portal.azure.com](https://portal.azure.com) → **Microsoft Entra ID** → **App registrations** → **New registration** 2. Configure: * **Name:** `CrewAI` (or your preferred name) * **Supported account types:** Accounts in this organizational directory only * **Redirect URI:** Select **Web**, enter `https:///auth/entra_id/callback` 3. Click **Register** From the app overview page, copy: * **Application (client) ID** → `ENTRA_ID_CLIENT_ID` * **Directory (tenant) ID** → `ENTRA_ID_TENANT_ID` 1. Navigate to **Certificates & Secrets** → **New client secret** 2. Add a description and select expiration period 3. Copy the secret value immediately (it won't be shown again) → `ENTRA_ID_CLIENT_SECRET` 1. Go to **Enterprise applications** → select your app 2. Under **Security** → **Permissions**, click **Grant admin consent** 3. Ensure **Microsoft Graph → User.Read** is granted Under **App registrations** → your app → **App roles**, create: | Display Name | Value | Allowed Member Types | | ------------- | --------------- | -------------------- | | Member | `member` | Users/Groups | | Factory Admin | `factory-admin` | Users/Groups | The `member` role grants login access. The `factory-admin` role grants admin panel access. Roles are included in the JWT automatically. 1. Under **Properties**, set **Assignment required?** to **Yes** 2. Under **Users and groups**, assign users/groups with the appropriate role ```yaml theme={null} envVars: AUTH_PROVIDER: "entra_id" secrets: ENTRA_ID_CLIENT_ID: "" ENTRA_ID_CLIENT_SECRET: "" ENTRA_ID_TENANT_ID: "" ``` To allow `crewai login` via Device Authorization Grant: 1. Under **Authentication** → **Advanced settings**, enable **Allow public client flows** 2. Under **Expose an API**, add an Application ID URI (e.g., `api://crewai-cli`) 3. Add a scope (e.g., `read`) with **Admins and users** consent 4. Under **Manifest**, set `accessTokenAcceptedVersion` to `2` 5. Add environment variables: ```yaml theme={null} secrets: ENTRA_ID_DEVICE_AUTHORIZATION_CLIENT_ID: "" ENTRA_ID_CUSTOM_OPENID_SCOPE: "" ``` *** ### Okta 1. Open Okta Admin Console → **Applications** → **Create App Integration** 2. Select **OIDC - OpenID Connect** → **Web Application** → **Next** 3. Configure: * **App integration name:** `CrewAI SSO` * **Sign-in redirect URI:** `https:///auth/okta/callback` * **Sign-out redirect URI:** `https://` * **Assignments:** Choose who can access (everyone or specific groups) 4. Click **Save** From the app details page: * **Client ID** → `OKTA_CLIENT_ID` * **Client Secret** → `OKTA_CLIENT_SECRET` * **Okta URL** (top-right corner, under your username) → `OKTA_SITE` 1. Navigate to **Security** → **API** 2. Select your authorization server (default: `default`) 3. Under **Access Policies**, add a policy and rule: * In the rule, under **Scopes requested**, select **The following scopes** → **OIDC default scopes** 4. Note the **Name** and **Audience** of the authorization server The authorization server name and audience must match `OKTA_AUTHORIZATION_SERVER` and `OKTA_AUDIENCE` exactly. Mismatches cause `401 Unauthorized` or `Invalid token: Signature verification failed` errors. ```yaml theme={null} envVars: AUTH_PROVIDER: "okta" secrets: OKTA_CLIENT_ID: "" OKTA_CLIENT_SECRET: "" OKTA_SITE: "https://your-domain.okta.com" OKTA_AUTHORIZATION_SERVER: "default" OKTA_AUDIENCE: "api://default" ``` 1. Create a **new** app integration: **OIDC** → **Native Application** 2. Enable **Device Authorization** and **Refresh Token** grant types 3. Allow everyone in your organization to access 4. Add environment variable: ```yaml theme={null} secrets: OKTA_DEVICE_AUTHORIZATION_CLIENT_ID: "" ``` Device Authorization requires a **Native Application** — it cannot use the Web Application created for browser-based SSO. *** ### Keycloak 1. Open Keycloak Admin Console → navigate to your realm 2. **Clients** → **Create client**: * **Client type:** OpenID Connect * **Client ID:** `crewai-factory` (suggested) 3. Capability config: * **Client authentication:** On * **Standard flow:** Checked 4. Login settings: * **Root URL:** `https://` * **Valid redirect URIs:** `https:///auth/keycloak/callback` * **Valid post logout redirect URIs:** `https://` 5. Click **Save** * **Client ID** → `KEYCLOAK_CLIENT_ID` * Under **Credentials** tab: **Client secret** → `KEYCLOAK_CLIENT_SECRET` * **Realm name** → `KEYCLOAK_REALM` * **Keycloak server URL** → `KEYCLOAK_SITE` ```yaml theme={null} envVars: AUTH_PROVIDER: "keycloak" secrets: KEYCLOAK_CLIENT_ID: "" KEYCLOAK_CLIENT_SECRET: "" KEYCLOAK_SITE: "https://keycloak.yourdomain.com" KEYCLOAK_REALM: "" KEYCLOAK_AUDIENCE: "account" # Only set if using a custom base path (pre-v17 migrations): # KEYCLOAK_BASE_URL: "/auth" ``` Keycloak includes `account` as the default audience in access tokens. For most installations, `KEYCLOAK_AUDIENCE=account` works without additional configuration. See [Keycloak audience documentation](https://www.keycloak.org/docs/latest/authorization_services/index.html) if you need a custom audience. 1. Create a **second** client: * **Client type:** OpenID Connect * **Client ID:** `crewai-factory-cli` (suggested) * **Client authentication:** Off (Device Authorization requires a public client) * **Authentication flow:** Check **only** OAuth 2.0 Device Authorization Grant 2. Add environment variable: ```yaml theme={null} secrets: KEYCLOAK_DEVICE_AUTHORIZATION_CLIENT_ID: "" ``` *** ### WorkOS 1. Create an application in the [WorkOS Dashboard](https://dashboard.workos.com) 2. Configure the redirect URI: `https:///auth/workos/callback` 3. Note the **Client ID** and **AuthKit domain** 4. Set up organizations in the WorkOS dashboard ```yaml theme={null} envVars: AUTH_PROVIDER: "workos" secrets: WORKOS_CLIENT_ID: "" WORKOS_AUTHKIT_DOMAIN: "" ``` *** ### Auth0 1. In the [Auth0 Dashboard](https://manage.auth0.com), create a new **Regular Web Application** 2. Configure: * **Allowed Callback URLs:** `https:///auth/auth0/callback` * **Allowed Logout URLs:** `https://` 3. Note the **Domain**, **Client ID**, and **Client Secret** ```yaml theme={null} envVars: AUTH_PROVIDER: "auth0" secrets: AUTH0_CLIENT_ID: "" AUTH0_CLIENT_SECRET: "" AUTH0_DOMAIN: "" ``` 1. Create a **Native** application in Auth0 for Device Authorization 2. Enable the **Device Authorization** grant type under application settings 3. Configure the CLI with the appropriate audience and client ID *** ## CLI Authentication The CrewAI CLI supports SSO authentication via the **Device Authorization Grant** flow. This allows developers to authenticate from their terminal without exposing credentials. ### Quick Setup For Factory installations, the CLI can auto-configure all OAuth2 settings: ```bash theme={null} crewai enterprise configure https://your-factory-url.app ``` This command fetches the SSO configuration from your Factory instance and sets all required CLI parameters automatically. Then authenticate: ```bash theme={null} crewai login ``` Requires CrewAI CLI version **1.6.0** or higher for Entra ID, **0.159.0** or higher for Okta, and **1.9.0** or higher for Keycloak. ### Manual CLI Configuration If you need to configure the CLI manually, use `crewai config set`: ```bash theme={null} # Set the provider crewai config set oauth2_provider okta # Set provider-specific values crewai config set oauth2_domain your-domain.okta.com crewai config set oauth2_client_id your-client-id crewai config set oauth2_audience api://default # Set the enterprise base URL crewai config set enterprise_base_url https://your-factory-url.app ``` ### CLI Configuration Reference | Setting | Description | Example | | --------------------- | ------------------------ | ------------------------------------------------- | | `enterprise_base_url` | Your CrewAI instance URL | `https://crewai.yourcompany.com` | | `oauth2_provider` | Provider name | `workos`, `okta`, `auth0`, `entra_id`, `keycloak` | | `oauth2_domain` | Provider domain | `your-domain.okta.com` | | `oauth2_client_id` | OAuth2 client ID | `0oaqnwji7pGW7VT6T697` | | `oauth2_audience` | API audience identifier | `api://default` | View current configuration: ```bash theme={null} crewai config list ``` ### How Device Authorization Works 1. Run `crewai login` — the CLI requests a device code from your IdP 2. A verification URL and code are displayed in your terminal 3. Your browser opens to the verification URL 4. Enter the code and authenticate with your IdP credentials 5. The CLI receives an access token and stores it locally *** ## Role-Based Access Control (RBAC) CrewAI Platform provides granular RBAC that integrates with your SSO provider. ### Permission Model | Permission | Description | | ---------- | ------------------------------------------------- | | **Read** | View resources (dashboards, automations, logs) | | **Write** | Create and modify resources | | **Manage** | Full control including deletion and configuration | ### Resources Permissions can be scoped to individual resources: * **Usage Dashboard** — Platform usage metrics and analytics * **Automations Dashboard** — Crew and flow management * **Environment Variables** — Secret and configuration management * **Individual Automations** — Per-automation access control ### Roles * **Predefined roles** come out of the box with standard permission sets * **Custom roles** can be created with any combination of permissions * **Per-resource assignment** — limit specific automations to individual users or roles ### Factory Admin Access For Factory deployments using Entra ID, admin access is controlled via App Roles: * Assign the `factory-admin` role to users who need admin panel access * Assign the `member` role for standard platform access * Roles are communicated via JWT claims — no additional configuration needed after IdP setup *** ## Troubleshooting ### Invalid Redirect URI **Symptom:** Authentication fails with a redirect URI mismatch error. **Fix:** Ensure the redirect URI in your IdP exactly matches the expected callback URL: | Provider | Callback URL | | -------- | ----------------------------------------- | | Entra ID | `https:///auth/entra_id/callback` | | Okta | `https:///auth/okta/callback` | | Keycloak | `https:///auth/keycloak/callback` | | WorkOS | `https:///auth/workos/callback` | | Auth0 | `https:///auth/auth0/callback` | ### CLI Login Fails (Device Authorization) **Symptom:** `crewai login` returns an error or times out. **Fix:** * Verify that Device Authorization Grant is enabled in your IdP * For Okta: ensure you have a **Native Application** (not Web) with Device Authorization grant * For Entra ID: ensure **Allow public client flows** is enabled * For Keycloak: ensure the CLI client has **Client authentication: Off** and only Device Authorization Grant enabled * Check that `*_DEVICE_AUTHORIZATION_CLIENT_ID` environment variable is set on the server ### Token Validation Errors **Symptom:** `Invalid token: Signature verification failed` or `401 Unauthorized` after login. **Fix:** * **Okta:** Verify `OKTA_AUTHORIZATION_SERVER` and `OKTA_AUDIENCE` match the authorization server's Name and Audience exactly * **Entra ID:** Ensure `accessTokenAcceptedVersion` is set to `2` in the app manifest * **Keycloak:** Verify `KEYCLOAK_AUDIENCE` matches the audience in your access tokens (default: `account`) ### Admin Consent Not Granted (Entra ID) **Symptom:** Users can't log in, see "needs admin approval" message. **Fix:** Go to **Enterprise applications** → your app → **Permissions** → **Grant admin consent**. Ensure `User.Read` is granted for Microsoft Graph. ### 403 Forbidden After Login **Symptom:** User authenticates successfully but gets 403 errors. **Fix:** * Check that the user is assigned to the application in your IdP * For Entra ID with **Assignment required = Yes**: ensure the user has a role assignment (Member or Factory Admin) * For Okta: verify the user or their group is assigned under the app's **Assignments** tab ### CLI Can't Reach Factory Instance **Symptom:** `crewai enterprise configure` fails to connect. **Fix:** * Verify the Factory URL is reachable from your machine * Check that `enterprise_base_url` is set correctly: `crewai config list` * Ensure TLS certificates are valid and trusted *** ## Environment Variables Reference ### Common | Variable | Description | | --------------- | ----------------------------------------------------------------------------------- | | `AUTH_PROVIDER` | Authentication provider: `entra_id`, `okta`, `workos`, `auth0`, `keycloak`, `local` | ### Microsoft Entra ID | Variable | Required | Description | | ----------------------------------------- | -------- | ----------------------------------------------------------------- | | `ENTRA_ID_CLIENT_ID` | ✅ | Application (client) ID from Azure | | `ENTRA_ID_CLIENT_SECRET` | ✅ | Client secret from Azure | | `ENTRA_ID_TENANT_ID` | ✅ | Directory (tenant) ID from Azure | | `ENTRA_ID_DEVICE_AUTHORIZATION_CLIENT_ID` | CLI only | Client ID for Device Authorization Grant | | `ENTRA_ID_CUSTOM_OPENID_SCOPE` | CLI only | Custom scope from "Expose an API" (e.g., `api://crewai-cli/read`) | ### Okta | Variable | Required | Description | | ------------------------------------- | -------- | ------------------------------------------------------------ | | `OKTA_CLIENT_ID` | ✅ | Okta application client ID | | `OKTA_CLIENT_SECRET` | ✅ | Okta client secret | | `OKTA_SITE` | ✅ | Okta organization URL (e.g., `https://your-domain.okta.com`) | | `OKTA_AUTHORIZATION_SERVER` | ✅ | Authorization server name (e.g., `default`) | | `OKTA_AUDIENCE` | ✅ | Authorization server audience (e.g., `api://default`) | | `OKTA_DEVICE_AUTHORIZATION_CLIENT_ID` | CLI only | Native app client ID for Device Authorization | ### WorkOS | Variable | Required | Description | | ----------------------- | -------- | ------------------------------------------------ | | `WORKOS_CLIENT_ID` | ✅ | WorkOS application client ID | | `WORKOS_AUTHKIT_DOMAIN` | ✅ | AuthKit domain (e.g., `your-domain.authkit.com`) | ### Auth0 | Variable | Required | Description | | --------------------- | -------- | --------------------------------------------------- | | `AUTH0_CLIENT_ID` | ✅ | Auth0 application client ID | | `AUTH0_CLIENT_SECRET` | ✅ | Auth0 client secret | | `AUTH0_DOMAIN` | ✅ | Auth0 tenant domain (e.g., `your-tenant.auth0.com`) | ### Keycloak | Variable | Required | Description | | ----------------------------------------- | -------- | ---------------------------------------------------- | | `KEYCLOAK_CLIENT_ID` | ✅ | Keycloak client ID | | `KEYCLOAK_CLIENT_SECRET` | ✅ | Keycloak client secret | | `KEYCLOAK_SITE` | ✅ | Keycloak server URL | | `KEYCLOAK_REALM` | ✅ | Keycloak realm name | | `KEYCLOAK_AUDIENCE` | ✅ | Token audience (default: `account`) | | `KEYCLOAK_BASE_URL` | Optional | Base URL path (e.g., `/auth` for pre-v17 migrations) | | `KEYCLOAK_DEVICE_AUTHORIZATION_CLIENT_ID` | CLI only | Public client ID for Device Authorization | *** ## Next Steps * [Installation Guide](https://docs.crewai.com/installation) — Get started with CrewAI * [Quickstart](https://docs.crewai.com/quickstart) — Build your first crew * [RBAC Setup](/platform/en/features/rbac) — Detailed role and permission management # Flows in Studio Source: https://docs-platform.crewai.com/platform/en/features/studio-flows Build event-driven workflows that combine deterministic, step-by-step control with agentic intelligence — no code required. **Rolling out now**: Flows in Studio is being rolled out gradually during the week of July 20th, 2026. If you don't see the Flows option in Studio yet, it hasn't reached your organization — check back soon. ## Overview Studio now supports building **Flows** in addition to Crews. Flows are event-driven workflows where you control exactly which steps run, in what order, and under what conditions — while still delegating the intelligent work within each step to AI agents. To build a Flow, open Studio, describe your automation, and select **Flows** from the selector next to the prompt box. Flows selector in Studio ## Why Flows? Crews are great when you want a team of agents to collaborate autonomously toward a goal. But many real-world automations need more predictability: fetch this data first, then summarize it, then post the result — every time, in that order. Flows give you both: * **Determinism where it matters**: steps execute in a defined sequence with explicit branching, so runs are predictable, repeatable, and easy to debug. * **Intelligence where you need it**: each step is powered by an agent (or an entire crew), so the work inside a step — summarizing, scoring, drafting, deciding — benefits from full LLM reasoning. This mix is what makes Flows well suited for production automations: the structure is guaranteed, and the agency is scoped to the steps that need it. ## Building a Flow Describe what you want in natural language and the Studio Assistant designs the Flow for you — creating the steps, wiring them together, and configuring the agents and app integrations each step needs. The canvas on the right shows the resulting workflow as connected nodes, and you can keep iterating conversationally or edit any node directly. Flow canvas with the Studio Assistant When you're ready, use **Run** to test the Flow end-to-end, inspect results in the **Output** and **Traces** tabs, and **Deploy** when it's stable. You can also **Share** the project or **Download** the source code to continue development outside Studio. Downloading source code is a one-way export. The Studio project remains the source of truth, and changes to downloaded code cannot be imported back. Deploying customized code creates a separate code-sourced automation without the Studio visual editor, versioning, or validation. ## Node Types Flows are composed from three core node types. Each node is a step in the workflow, and you can mix them freely. ### Single Agent A Single Agent node runs one agent against one focused task — ideal for well-scoped steps like fetching data from an integration, transforming content, or posting a message. Clicking into an agent node opens its full configuration: * **Task**: what this step should accomplish and what output it should produce * **Profile**: the agent's role, goal, and backstory * **Model**: which LLM powers the agent * **Apps**: the integrations the agent can use (e.g. Linear, Slack, HubSpot) * **Runtime Controls**: toggles for planning before executing, delegation, and memory Single Agent node configuration ### Crews A Crew node embeds an entire crew — multiple agents collaborating across multiple tasks — as a single step in your Flow. Use it when a step is too rich for one agent, like grouping and summarizing data by team and then formatting the result for delivery. Crew node in a Flow Opening a Crew node reveals its internal structure: the tasks it performs, the agents assigned to each, and the apps they use. The crew runs autonomously within the step, then hands its output to the next node in the Flow. Inside a Crew node This is the deterministic-plus-agentic pattern in action: the Flow guarantees *when* the crew runs, and the crew brings collaborative intelligence to *how* the work gets done. ### Router A Router node branches the Flow based on conditions, so different outcomes take different paths. For example, a lead-routing Flow can score incoming leads and then route high-quality leads to a sales-assignment step while logging the rest for future nurturing. Router node with conditional branches Routers are what make Flows genuinely event-driven: the same workflow handles every case, but each run follows only the branch its data warrants — no wasted steps, no ambiguity about what happens next. ## Agent Repository Sync Agents you build in Flows don't have to stay locked inside a single project. Every agent node includes a **Publish to Agent Repository** button that saves the agent — its role, goal, backstory, model, and configuration — to your organization's [Agent Repository](/platform/en/features/agent-repositories). This works in both directions: * **Publish**: promote an agent you've refined in a Flow to the repository so other teams and projects can reuse it. * **Pull**: bring an existing repository agent into a new Flow instead of rebuilding it from scratch. Because repository agents are synced across your organization, an improvement made to a shared agent benefits every Flow that uses it — keeping agent behavior consistent, governed, and free of duplicated effort. ## Best Practices * **Reach for a Flow** when the automation has a clear sequence or branching logic; reach for a Crew when the path to the goal is open-ended. * **Keep agent tasks focused** — a Single Agent node with a tight task description is more reliable than one asked to do three things. * **Use Routers to handle every case explicitly**, including the "do nothing" path (e.g. logging skipped leads), so runs are fully accounted for. * **Publish stable agents to the Agent Repository** so your organization builds a shared library instead of parallel one-offs. * **Test with Run and inspect Traces** before deploying to catch integration or prompt issues early. ## Related Build Crews in Studio. Share and reuse agents across your organization. Learn how Flows work in the CrewAI framework. Connect the apps your agents use. # Tools & Integrations Source: https://docs-platform.crewai.com/platform/en/features/tools-and-integrations Connect external apps and manage internal tools your agents can use. ## Overview Tools & Integrations is the central hub for connecting third‑party apps and managing internal tools that your agents can use at runtime. Tools & Integrations Overview ## Explore ## Agent Apps (Integrations) Connect enterprise‑grade applications (e.g., Gmail, Google Drive, HubSpot, Slack) via OAuth to enable agent actions. Click Connect on an app and complete OAuth. Optionally adjust scopes, triggers, and action availability. Connected services become available as tools for your agents. Integrations Grid ### Connect your Account 1. Go to Integrations 2. Click Connect on the desired service 3. Complete the OAuth flow and grant scopes 4. Copy your Enterprise Token from Integration Settings Enterprise Token ### Install Integration Tools To use the integrations locally, you need to install the latest `crewai-tools` package. ```bash theme={null} uv add crewai-tools ``` ### Environment Variable Setup To use integrations with `Agent(apps=[])`, you must set the `CREWAI_PLATFORM_INTEGRATION_TOKEN` environment variable with your Enterprise Token. ```bash theme={null} export CREWAI_PLATFORM_INTEGRATION_TOKEN="your_enterprise_token" ``` Or add it to your `.env` file: ``` CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token ``` ### Usage Example Use the new streamlined approach to integrate enterprise apps. Simply specify the app and its actions directly in the Agent configuration. ```python theme={null} from crewai import Agent, Task, Crew # Create an agent with Gmail capabilities email_agent = Agent( role="Email Manager", goal="Manage and organize email communications", backstory="An AI assistant specialized in email management and communication.", apps=['gmail', 'gmail/send_email'] # Using canonical name 'gmail' ) # Task to send an email email_task = Task( description="Draft and send a follow-up email to john@example.com about the project update", agent=email_agent, expected_output="Confirmation that email was sent successfully" ) # Run the task crew = Crew( agents=[email_agent], tasks=[email_task] ) # Run the crew crew.kickoff() ``` ### Filtering Tools ```python theme={null} from crewai import Agent, Task, Crew # Create agent with specific Gmail actions only gmail_agent = Agent( role="Gmail Manager", goal="Manage gmail communications and notifications", backstory="An AI assistant that helps coordinate gmail communications.", apps=['gmail/fetch_emails'] # Using canonical name with specific action ) notification_task = Task( description="Find the email from john@example.com", agent=gmail_agent, expected_output="Email found from john@example.com" ) crew = Crew( agents=[gmail_agent], tasks=[notification_task] ) ``` On a deployed crew, you can specify which actions are available for each integration from the service settings page. Filter Actions ### Scoped Deployments (multi‑user orgs) You can scope each integration to a specific user. For example, a crew that connects to Google can use a specific user’s Gmail account. Useful when different teams/users must keep data access separated. Use the `user_bearer_token` to scope authentication to the requesting user. If the user isn’t logged in, the crew won’t use connected integrations. Otherwise it falls back to the default bearer token configured for the deployment. User Bearer Token
### Catalog #### Communication & Collaboration * Gmail — Manage emails and drafts * Slack — Workspace notifications and alerts * Microsoft — Office 365 and Teams integration #### Project Management * Jira — Issue tracking and project management * ClickUp — Task and productivity management * Asana — Team task and project coordination * Notion — Page and database management * Linear — Software project and bug tracking * GitHub — Repository and issue management #### Customer Relationship Management * Salesforce — CRM account and opportunity management * HubSpot — Sales pipeline and contact management * Zendesk — Customer support ticket management #### Business & Finance * Stripe — Payment processing and customer management * Shopify — E‑commerce store and product management #### Productivity & Storage * Google Sheets — Spreadsheet data synchronization * Google Calendar — Event and schedule management * Box — File storage and document management …and more to come! ## Internal Tools Create custom tools locally, publish them on CrewAI AMP Tool Repository and use them in your agents. Before running the commands below, make sure you log in to your CrewAI AMP account by running this command: `bash crewai login ` Internal Tool Detail Create a new tool locally. `bash crewai tool create your-tool ` Publish the tool to the CrewAI AMP Tool Repository. `bash crewai tool publish ` Install the tool from the CrewAI AMP Tool Repository. `bash crewai tool install your-tool ` Manage: * Name and description * Visibility (Private / Public) * Required environment variables * Version history and downloads * Team and role access Internal Tool Detail ## Related Create, publish, and version custom tools for your organization. Automate workflows and integrate with external platforms and services. # Traces Source: https://docs-platform.crewai.com/platform/en/features/traces Using Traces to monitor your Crews ## Overview Traces provide comprehensive visibility into your crew executions, helping you monitor performance, debug issues, and optimize your AI agent workflows. ## What are Traces? Traces in CrewAI AMP are detailed execution records that capture every aspect of your crew's operation, from initial inputs to final outputs. They record: * Agent thoughts and reasoning * Task execution details * Tool usage and outputs * Token consumption metrics * Execution times * Cost estimates Traces Overview ## Accessing Traces Once in your CrewAI AMP dashboard, click on the **Traces** to view all execution records. You'll see a list of all crew executions, sorted by date. Click on any execution to view its detailed trace. ## Understanding the Trace Interface The trace interface is divided into several sections, each providing different insights into your crew's execution: ### 1. Execution Summary The top section displays high-level metrics about the execution: * **Total Tokens**: Number of tokens consumed across all tasks * **Prompt Tokens**: Tokens used in prompts to the LLM * **Completion Tokens**: Tokens generated in LLM responses * **Requests**: Number of API calls made * **Execution Time**: Total duration of the crew run * **Estimated Cost**: Approximate cost based on token usage Execution Summary ### 2. Tasks & Agents This section shows all tasks and agents that were part of the crew execution: * Task name and agent assignment * Agents and LLMs used for each task * Status (completed/failed) * Individual execution time of the task Task List ### 3. Final Output Displays the final result produced by the crew after all tasks are completed. Final Output ### 4. Execution Timeline A visual representation of when each task started and ended, helping you identify bottlenecks or parallel execution patterns. Execution Timeline ### 5. Detailed Task View When you click on a specific task in the timeline or task list, you'll see: Detailed Task View * **Task Key**: Unique identifier for the task * **Task ID**: Technical identifier in the system * **Status**: Current state (completed/running/failed) * **Agent**: Which agent performed the task * **LLM**: Language model used for this task * **Start/End Time**: When the task began and completed * **Execution Time**: Duration of this specific task * **Task Description**: What the agent was instructed to do * **Expected Output**: What output format was requested * **Input**: Any input provided to this task from previous tasks * **Output**: The actual result produced by the agent ## Using Traces for Debugging Traces are invaluable for troubleshooting issues with your crews: When a crew execution doesn't produce the expected results, examine the trace to find where things went wrong. Look for: * Failed tasks * Unexpected agent decisions * Tool usage errors * Misinterpreted instructions Failure Points Use execution metrics to identify performance bottlenecks: * Tasks that took longer than expected * Excessive token usage * Redundant tool operations * Unnecessary API calls Analyze token usage and cost estimates to optimize your crew's efficiency: * Consider using smaller models for simpler tasks * Refine prompts to be more concise * Cache frequently accessed information * Structure tasks to minimize redundant operations ## Performance and batching CrewAI batches trace uploads to reduce overhead on high-volume runs: * A TraceBatchManager buffers events and sends them in batches via the Plus API client * Reduces network chatter and improves reliability on flaky connections * Automatically enabled in the default trace listener; no configuration needed This yields more stable tracing under load while preserving detailed task/agent telemetry. Contact our support team for assistance with trace analysis or any other CrewAI AMP features. # Webhook Streaming Source: https://docs-platform.crewai.com/platform/en/features/webhook-streaming Using Webhook Streaming to stream events to your webhook ## Overview Enterprise Event Streaming lets you receive real-time webhook updates about your crews and flows deployed to CrewAI AMP, such as model calls, tool usage, and flow steps. ## Usage When using the Kickoff API, include a `webhooks` object to your request, for example: ```json theme={null} { "inputs": { "foo": "bar" }, "webhooks": { "events": ["crew_kickoff_started", "llm_call_started"], "url": "https://your.endpoint/webhook", "realtime": false, "authentication": { "strategy": "bearer", "token": "my-secret-token" } } } ``` If `realtime` is set to `true`, each event is delivered individually and immediately, at the cost of crew/flow performance. ## Webhook Format Each webhook sends a list of events: ```json theme={null} { "events": [ { "id": "event-id", "execution_id": "crew-run-id", "timestamp": "2025-02-16T10:58:44.965Z", "type": "llm_call_started", "data": { "model": "gpt-4", "messages": [ { "role": "system", "content": "You are an assistant." }, { "role": "user", "content": "Summarize this article." } ] } } ] } ``` The `data` object structure varies by event type. Refer to the [event list](https://github.com/crewAIInc/crewAI/tree/main/lib/crewai/src/crewai/events/types) on GitHub. As requests are sent over HTTP, the order of events can't be guaranteed. If you need ordering, use the `timestamp` field. ## Supported Events CrewAI supports both system events and custom events in Enterprise Event Streaming. These events are sent to your configured webhook endpoint during crew and flow execution. ### Flow Events: * `flow_created` * `flow_started` * `flow_finished` * `flow_plot` * `method_execution_started` * `method_execution_finished` * `method_execution_failed` ### Agent Events: * `agent_execution_started` * `agent_execution_completed` * `agent_execution_error` * `lite_agent_execution_started` * `lite_agent_execution_completed` * `lite_agent_execution_error` * `agent_logs_started` * `agent_logs_execution` * `agent_evaluation_started` * `agent_evaluation_completed` * `agent_evaluation_failed` ### Crew Events: * `crew_kickoff_started` * `crew_kickoff_completed` * `crew_kickoff_failed` * `crew_train_started` * `crew_train_completed` * `crew_train_failed` * `crew_test_started` * `crew_test_completed` * `crew_test_failed` * `crew_test_result` ### Task Events: * `task_started` * `task_completed` * `task_failed` * `task_evaluation` ### Tool Usage Events: * `tool_usage_started` * `tool_usage_finished` * `tool_usage_error` * `tool_validate_input_error` * `tool_selection_error` * `tool_execution_error` ### LLM Events: * `llm_call_started` * `llm_call_completed` * `llm_call_failed` * `llm_stream_chunk` ### LLM Guardrail Events: * `llm_guardrail_started` * `llm_guardrail_completed` ### Memory Events: * `memory_query_started` * `memory_query_completed` * `memory_query_failed` * `memory_save_started` * `memory_save_completed` * `memory_save_failed` * `memory_retrieval_started` * `memory_retrieval_completed` ### Knowledge Events: * `knowledge_search_query_started` * `knowledge_search_query_completed` * `knowledge_search_query_failed` * `knowledge_query_started` * `knowledge_query_completed` * `knowledge_query_failed` ### Reasoning Events: * `agent_reasoning_started` * `agent_reasoning_completed` * `agent_reasoning_failed` Event names match the internal event bus. See GitHub for the full list of events. You can emit your own custom events, and they will be delivered through the webhook stream alongside system events. Full list of events Contact our support team for assistance with webhook integration or troubleshooting. # Triggers Overview Source: https://docs-platform.crewai.com/platform/en/guides/automation-triggers Understand how CrewAI AMP triggers work, how to manage them, and where to find integration-specific playbooks CrewAI AMP triggers connect your automations to real-time events across the tools your teams already use. Instead of polling systems or relying on manual kickoffs, triggers listen for changes—new emails, calendar updates, CRM status changes—and immediately launch the crew or flow you specify. Automation Triggers Overview ### Integration Playbooks Deep-dive guides walk through setup and sample workflows for each integration: Enable crews when emails arrive or threads update. React to calendar events as they are created, updated, or cancelled. Handle Drive file uploads, edits, and deletions. Automate responses to new Outlook messages and calendar updates. Audit file activity and sharing changes in OneDrive. Kick off workflows when new Teams chats start. Launch automations from HubSpot workflows and lifecycle events. Connect Salesforce processes to CrewAI for CRM automation. Start crews directly from Slack slash commands. Bridge CrewAI with thousands of Zapier-supported apps. ## Trigger Capabilities With triggers, you can: * **Respond to real-time events** - Automatically execute workflows when specific conditions are met * **Integrate with external systems** - Connect with platforms like Gmail, Outlook, OneDrive, JIRA, Slack, Stripe and more * **Scale your automation** - Handle high-volume events without manual intervention * **Maintain context** - Access trigger data within your crews and flows ## Managing Triggers ### Viewing Available Triggers To access and manage your automation triggers: 1. Navigate to your deployment in the CrewAI dashboard 2. Click on the **Triggers** tab to view all available trigger integrations List of available automation triggers This view shows all the trigger integrations available for your deployment, along with their current connection status. ### Enabling and Disabling Triggers Each trigger can be easily enabled or disabled using the toggle switch: Enable or disable triggers with toggle * **Enabled (blue toggle)**: The trigger is active and will automatically execute your deployment when the specified events occur * **Disabled (gray toggle)**: The trigger is inactive and will not respond to events Simply click the toggle to change the trigger state. Changes take effect immediately. ### Monitoring Trigger Executions Track the performance and history of your triggered executions: List of executions triggered by automation ## Building Trigger-Driven Automations Before building your automation, it's helpful to understand the structure of trigger payloads that your crews and flows will receive. ### Trigger Setup Checklist Before wiring a trigger into production, make sure you: * Connect the integration under **Tools & Integrations** and complete any OAuth or API key steps * Enable the trigger toggle on the deployment that should respond to events * Provide any required environment variables (API tokens, tenant IDs, shared secrets) * Create or update tasks that can parse the incoming payload within the first crew task or flow step * Decide whether to pass trigger context automatically using `allow_crewai_trigger_context` * Set up monitoring—webhook logs, CrewAI execution history, and optional external alerting ### Testing Triggers Locally with CLI The CrewAI CLI provides powerful commands to help you develop and test trigger-driven automations without deploying to production. #### List Available Triggers View all available triggers for your connected integrations: ```bash theme={null} crewai triggers list ``` This command displays all triggers available based on your connected integrations, showing: * Integration name and connection status * Available trigger types * Trigger names and descriptions #### Simulate Trigger Execution Test your crew with realistic trigger payloads before deployment: ```bash theme={null} crewai triggers run ``` For example: ```bash theme={null} crewai triggers run microsoft_onedrive/file_changed ``` This command: * Executes your crew locally * Passes a complete, realistic trigger payload * Simulates exactly how your crew will be called in production **Important Development Notes:** * Use `crewai triggers run ` to simulate trigger execution during development * Using `crewai run` will NOT simulate trigger calls and won't pass the trigger payload * After deployment, your crew will be executed with the actual trigger payload * If your crew expects parameters that aren't in the trigger payload, execution may fail ### Triggers with Crew Your existing crew definitions work seamlessly with triggers, you just need to have a task to parse the received payload: ```python theme={null} @CrewBase class MyAutomatedCrew: @agent def researcher(self) -> Agent: return Agent( config=self.agents_config['researcher'], ) @task def parse_trigger_payload(self) -> Task: return Task( config=self.tasks_config['parse_trigger_payload'], agent=self.researcher(), ) @task def analyze_trigger_content(self) -> Task: return Task( config=self.tasks_config['analyze_trigger_data'], agent=self.researcher(), ) ``` The crew will automatically receive and can access the trigger payload through the standard CrewAI context mechanisms. Crew and Flow inputs can include `crewai_trigger_payload`. CrewAI automatically injects this payload: - Tasks: appended to the first task's description by default ("Trigger Payload: ") - Control via `allow_crewai_trigger_context`: set `True` to always inject, `False` to never inject - Flows: any `@start()` method that accepts a `crewai_trigger_payload` parameter will receive it ### Integration with Flows For flows, you have more control over how trigger data is handled: #### Accessing Trigger Payload All `@start()` methods in your flows will accept an additional parameter called `crewai_trigger_payload`: ```python theme={null} from crewai.flow import Flow, start, listen class MyAutomatedFlow(Flow): @start() def handle_trigger(self, crewai_trigger_payload: dict = None): """ This start method can receive trigger data """ if crewai_trigger_payload: # Process the trigger data trigger_id = crewai_trigger_payload.get('id') event_data = crewai_trigger_payload.get('payload', {}) # Store in flow state for use by other methods self.state.trigger_id = trigger_id self.state.trigger_type = event_data return event_data # Handle manual execution return None @listen(handle_trigger) def process_data(self, trigger_data): """ Process the data from the trigger """ # ... process the trigger ``` #### Triggering Crews from Flows When kicking off a crew within a flow that was triggered, pass the trigger payload as it: ```python theme={null} @start() def delegate_to_crew(self, crewai_trigger_payload: dict = None): """ Delegate processing to a specialized crew """ crew = MySpecializedCrew() # Pass the trigger payload to the crew result = crew.crew().kickoff( inputs={ 'a_custom_parameter': "custom_value", 'crewai_trigger_payload': crewai_trigger_payload }, ) return result ``` ## Troubleshooting **Trigger not firing:** * Verify the trigger is enabled in your deployment's Triggers tab * Check integration connection status under Tools & Integrations * Ensure all required environment variables are properly configured **Execution failures:** * Check the execution logs for error details * Use `crewai triggers run ` to test locally and see the exact payload structure * Verify your crew can handle the `crewai_trigger_payload` parameter * Ensure your crew doesn't expect parameters that aren't included in the trigger payload **Development issues:** * Always test with `crewai triggers run ` before deploying to see the complete payload * Remember that `crewai run` does NOT simulate trigger calls—use `crewai triggers run` instead * Use `crewai triggers list` to verify which triggers are available for your connected integrations * After deployment, your crew will receive the actual trigger payload, so test thoroughly locally first Automation triggers transform your CrewAI deployments into responsive, event-driven systems that can seamlessly integrate with your existing business processes and tools. # Azure OpenAI Setup Source: https://docs-platform.crewai.com/platform/en/guides/azure-openai-setup Configure Azure OpenAI with Crew Studio for enterprise LLM connections This guide walks you through connecting Azure OpenAI with Crew Studio for seamless enterprise AI operations. ## Setup Process 1. In Azure, go to [Azure AI Foundry](https://ai.azure.com/) > select your Azure OpenAI deployment. 2. On the left menu, click `Deployments`. If you don't have one, create a deployment with your desired model. 3. Once created, select your deployment and locate the `Target URI` and `Key` on the right side of the page. Keep this page open, as you'll need this information. Azure AI Foundry 4. In another tab, open `CrewAI AMP > LLM Connections`. Name your LLM Connection, select Azure as the provider, and choose the same model you selected in Azure. 5. On the same page, add environment variables from step 3: * One named `AZURE_DEPLOYMENT_TARGET_URL` (using the Target URI). The URL should look like this: [https://your-deployment.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-08-01-preview](https://your-deployment.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2024-08-01-preview) * Another named `AZURE_API_KEY` (using the Key). 6. Click `Add Connection` to save your LLM Connection. 7. In `CrewAI AMP > Settings > Defaults > Crew Studio LLM Settings`, set the new LLM Connection and model as defaults. 8. Ensure network access settings: * In Azure, go to `Azure OpenAI > select your deployment`. * Navigate to `Resource Management > Networking`. * Ensure that `Allow access from all networks` is enabled. If this setting is restricted, CrewAI may be blocked from accessing your Azure OpenAI endpoint. ## Verification You're all set! Crew Studio will now use your Azure OpenAI connection. Test the connection by creating a simple crew or task to ensure everything is working properly. ## Troubleshooting If you encounter issues: * Verify the Target URI format matches the expected pattern * Check that the API key is correct and has proper permissions * Ensure network access is configured to allow CrewAI connections * Confirm the deployment model matches what you've configured in CrewAI # Build Crew Source: https://docs-platform.crewai.com/platform/en/guides/build-crew A Crew is a group of agents that work together to complete a task. ## Overview [CrewAI AMP](https://app.crewai.com) streamlines the process of **creating**, **deploying**, and **managing** your AI agents in production environments. ## Getting Started