mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-04-22 10:52:37 +00:00
Compare commits
4 Commits
0.159.0
...
devin/1755
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9babfae81 | ||
|
|
2c98d0c1d9 | ||
|
|
ac69573afa | ||
|
|
70104e9651 |
@@ -238,8 +238,7 @@
|
||||
"en/observability/opik",
|
||||
"en/observability/patronus-evaluation",
|
||||
"en/observability/portkey",
|
||||
"en/observability/weave",
|
||||
"en/observability/truefoundry"
|
||||
"en/observability/weave"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -282,7 +281,6 @@
|
||||
{
|
||||
"group": "Features",
|
||||
"pages": [
|
||||
"en/enterprise/features/rbac",
|
||||
"en/enterprise/features/tool-repository",
|
||||
"en/enterprise/features/webhook-streaming",
|
||||
"en/enterprise/features/traces",
|
||||
@@ -346,7 +344,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Endpoints",
|
||||
"openapi": "https://raw.githubusercontent.com/crewAIInc/crewAI/main/docs/enterprise-api.en.yaml"
|
||||
"openapi": "enterprise-api.yaml"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -355,7 +353,7 @@
|
||||
"groups": [
|
||||
{
|
||||
"group": "Examples",
|
||||
"pages": ["en/examples/example", "en/examples/cookbooks"]
|
||||
"pages": ["en/examples/example"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -577,8 +575,7 @@
|
||||
"pt-BR/observability/opik",
|
||||
"pt-BR/observability/patronus-evaluation",
|
||||
"pt-BR/observability/portkey",
|
||||
"pt-BR/observability/weave",
|
||||
"pt-BR/observability/truefoundry"
|
||||
"pt-BR/observability/weave"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -621,7 +618,6 @@
|
||||
{
|
||||
"group": "Funcionalidades",
|
||||
"pages": [
|
||||
"pt-BR/enterprise/features/rbac",
|
||||
"pt-BR/enterprise/features/tool-repository",
|
||||
"pt-BR/enterprise/features/webhook-streaming",
|
||||
"pt-BR/enterprise/features/traces",
|
||||
@@ -686,7 +682,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Endpoints",
|
||||
"openapi": "https://raw.githubusercontent.com/crewAIInc/crewAI/main/docs/enterprise-api.pt-BR.yaml"
|
||||
"openapi": "enterprise-api.yaml"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -695,7 +691,7 @@
|
||||
"groups": [
|
||||
{
|
||||
"group": "Exemplos",
|
||||
"pages": ["pt-BR/examples/example", "pt-BR/examples/cookbooks"]
|
||||
"pages": ["pt-BR/examples/example"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -969,7 +965,6 @@
|
||||
{
|
||||
"group": "특징",
|
||||
"pages": [
|
||||
"ko/enterprise/features/rbac",
|
||||
"ko/enterprise/features/tool-repository",
|
||||
"ko/enterprise/features/webhook-streaming",
|
||||
"ko/enterprise/features/traces",
|
||||
@@ -1033,7 +1028,7 @@
|
||||
},
|
||||
{
|
||||
"group": "Endpoints",
|
||||
"openapi": "https://raw.githubusercontent.com/crewAIInc/crewAI/main/docs/enterprise-api.ko.yaml"
|
||||
"openapi": "enterprise-api.yaml"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1042,7 +1037,7 @@
|
||||
"groups": [
|
||||
{
|
||||
"group": "예시",
|
||||
"pages": ["ko/examples/example", "ko/examples/cookbooks"]
|
||||
"pages": ["ko/examples/example"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
title: "Role-Based Access Control (RBAC)"
|
||||
description: "Control access to crews, tools, and data with roles, scopes, and granular permissions."
|
||||
icon: "shield"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
RBAC in CrewAI Enterprise enables secure, scalable access management through a combination of organization‑level roles and automation‑level visibility controls.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/users_and_roles.png" alt="RBAC overview in CrewAI Enterprise" />
|
||||
|
||||
</Frame>
|
||||
|
||||
## 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.
|
||||
|
||||
<Steps>
|
||||
<Step title="Open Roles settings">
|
||||
Go to <b>Settings → Roles</b> in CrewAI Enterprise.
|
||||
</Step>
|
||||
<Step title="Choose a role type">
|
||||
Use a predefined role (<b>Owner</b>, <b>Member</b>) or click <b>Create role</b> to define a custom one.
|
||||
</Step>
|
||||
<Step title="Assign to members">
|
||||
Select users and assign the role. You can change this anytime.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### 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 |
|
||||
|
||||
## Automation‑level Access Control
|
||||
|
||||
In addition to organization‑wide roles, CrewAI Automations support fine‑grained visibility settings that let you restrict access to specific automations 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:
|
||||
|
||||
- View the deployment
|
||||
- Run it or interact with its API
|
||||
- Access its logs, metrics, and settings
|
||||
|
||||
The organization owner always has access, regardless of visibility settings.
|
||||
|
||||
You can configure automation‑level access control in Automation → Settings → Visibility tab.
|
||||
|
||||
<Steps>
|
||||
<Step title="Open Visibility tab">
|
||||
Navigate to <b>Automation → Settings → Visibility</b>.
|
||||
</Step>
|
||||
<Step title="Set visibility">
|
||||
Choose <b>Private</b> to restrict access. The organization owner always retains access.
|
||||
</Step>
|
||||
<Step title="Whitelist access">
|
||||
Add specific users and roles allowed to view, run, and access logs/metrics/settings.
|
||||
</Step>
|
||||
<Step title="Save and verify">
|
||||
Save changes, then confirm that non‑whitelisted users cannot view or run the automation.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Private visibility: access outcomes
|
||||
|
||||
| Action | Owner | Whitelisted user/role | Not whitelisted |
|
||||
|:---|:---|:---|:---|
|
||||
| View automation | ✓ | ✓ | ✗ |
|
||||
| Run automation/API | ✓ | ✓ | ✗ |
|
||||
| Access logs/metrics/settings | ✓ | ✓ | ✗ |
|
||||
|
||||
<Tip>
|
||||
The organization owner always has access. In private mode, only whitelisted users and roles can view, run, and access logs/metrics/settings.
|
||||
</Tip>
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/visibility.png" alt="Automation Visibility settings in CrewAI Enterprise" />
|
||||
|
||||
</Frame>
|
||||
|
||||
<Card title="Need Help?" icon="headset" href="mailto:support@crewai.com">
|
||||
Contact our support team for assistance with RBAC questions.
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: CrewAI Cookbooks
|
||||
description: Feature-focused quickstarts and notebooks for learning patterns fast.
|
||||
icon: book
|
||||
---
|
||||
|
||||
## Quickstarts & Demos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Task Guardrails" icon="shield-check" href="https://github.com/crewAIInc/crewAI-quickstarts/tree/main/Task%20Guardrails">
|
||||
Interactive notebooks for hands-on exploration.
|
||||
</Card>
|
||||
<Card title="Browse Quickstarts" icon="bolt" href="https://github.com/crewAIInc/crewAI-quickstarts">
|
||||
Feature demos and small projects showcasing specific CrewAI capabilities.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Use Cookbooks to learn a pattern quickly, then jump to Full Examples for production‑grade implementations.
|
||||
</Tip>
|
||||
|
||||
|
||||
@@ -1,85 +1,62 @@
|
||||
---
|
||||
title: CrewAI Examples
|
||||
description: Explore curated examples organized by Crews, Flows, Integrations, and Notebooks.
|
||||
description: A collection of examples that show how to use CrewAI framework to automate workflows.
|
||||
icon: rocket-launch
|
||||
---
|
||||
|
||||
## Crews
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Marketing Strategy" icon="bullhorn" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/marketing_strategy">
|
||||
Multi‑agent marketing campaign planning.
|
||||
</Card>
|
||||
<Card title="Surprise Trip" icon="plane" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/surprise_trip">
|
||||
Personalized surprise travel planning.
|
||||
</Card>
|
||||
<Card title="Match Profile to Positions" icon="id-card" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/match_profile_to_positions">
|
||||
CV‑to‑job matching with vector search.
|
||||
</Card>
|
||||
<Card title="Job Posting" icon="newspaper" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/job-posting">
|
||||
Automated job description creation.
|
||||
</Card>
|
||||
<Card title="Game Builder Crew" icon="gamepad" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/game-builder-crew">
|
||||
Multi‑agent team that designs and builds Python games.
|
||||
</Card>
|
||||
<Card title="Recruitment" icon="user-group" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/recruitment">
|
||||
Candidate sourcing and evaluation.
|
||||
</Card>
|
||||
<Card title="Browse all Crews" icon="users" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews">
|
||||
See the full list of crew examples.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Flows
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Content Creator Flow" icon="pen" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/content_creator_flow">
|
||||
Multi‑crew content generation with routing.
|
||||
</Card>
|
||||
<Card title="Email Auto Responder" icon="envelope" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/email_auto_responder_flow">
|
||||
Automated email monitoring and replies.
|
||||
</Card>
|
||||
<Card title="Lead Score Flow" icon="chart-line" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/lead_score_flow">
|
||||
Lead qualification with human‑in‑the‑loop.
|
||||
</Card>
|
||||
<Card title="Meeting Assistant Flow" icon="calendar" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/meeting_assistant_flow">
|
||||
Notes processing with integrations.
|
||||
</Card>
|
||||
<Card title="Self Evaluation Loop" icon="rotate" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/self_evaluation_loop_flow">
|
||||
Iterative self‑improvement workflows.
|
||||
</Card>
|
||||
<Card title="Write a Book (Flows)" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/write_a_book_with_flows">
|
||||
Parallel chapter generation.
|
||||
</Card>
|
||||
<Card title="Browse all Flows" icon="diagram-project" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows">
|
||||
See the full list of flow examples.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Integrations
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="CrewAI ↔ LangGraph" icon="link" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/crewai-langgraph">
|
||||
Integration with LangGraph framework.
|
||||
</Card>
|
||||
<Card title="Azure OpenAI" icon="cloud" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/azure_model">
|
||||
Using CrewAI with Azure OpenAI.
|
||||
</Card>
|
||||
<Card title="NVIDIA Models" icon="microchip" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/nvidia_models">
|
||||
NVIDIA ecosystem integrations.
|
||||
</Card>
|
||||
<Card title="Browse Integrations" icon="puzzle-piece" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations">
|
||||
See all integration examples.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Notebooks
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Simple QA Crew + Flow" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks/Simple%20QA%20Crew%20%2B%20Flow">
|
||||
Simple QA Crew + Flow.
|
||||
</Card>
|
||||
<Card title="All Notebooks" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks">
|
||||
Interactive examples for learning and experimentation.
|
||||
<Card
|
||||
title="Marketing Strategy"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/marketing_strategy"
|
||||
icon="bullhorn"
|
||||
iconType="solid"
|
||||
>
|
||||
Automate marketing strategy creation with CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Surprise Trip"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/surprise_trip"
|
||||
icon="plane"
|
||||
iconType="duotone"
|
||||
>
|
||||
Create a surprise trip itinerary with CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Match Profile to Positions"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/match_profile_to_positions"
|
||||
icon="linkedin"
|
||||
iconType="duotone"
|
||||
>
|
||||
Match a profile to jobpositions with CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Create Job Posting"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/job-posting"
|
||||
icon="newspaper"
|
||||
iconType="duotone"
|
||||
>
|
||||
Create a job posting with CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Game Generator"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/game-builder-crew"
|
||||
icon="gamepad"
|
||||
iconType="duotone"
|
||||
>
|
||||
Create a game with CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Find Job Candidates"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/recruitment"
|
||||
icon="user-group"
|
||||
iconType="duotone"
|
||||
>
|
||||
Find job candidates with CrewAI.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
title: TrueFoundry Integration
|
||||
icon: chart-line
|
||||
---
|
||||
|
||||
TrueFoundry provides an enterprise-ready [AI Gateway](https://www.truefoundry.com/ai-gateway) which can integrate with agentic frameworks like CrewAI and provides governance and observability for your AI Applications. TrueFoundry AI Gateway serves as a unified interface for LLM access, providing:
|
||||
|
||||
- **Unified API Access**: Connect to 250+ LLMs (OpenAI, Claude, Gemini, Groq, Mistral) through one API
|
||||
- **Low Latency**: Sub-3ms internal latency with intelligent routing and load balancing
|
||||
- **Enterprise Security**: SOC 2, HIPAA, GDPR compliance with RBAC and audit logging
|
||||
- **Quota and cost management**: Token-based quotas, rate limiting, and comprehensive usage tracking
|
||||
- **Observability**: Full request/response logging, metrics, and traces with customizable retention
|
||||
|
||||
## How TrueFoundry Integrates with CrewAI
|
||||
|
||||
|
||||
### Installation & Setup
|
||||
|
||||
<Steps>
|
||||
<Step title="Install CrewAI">
|
||||
```bash
|
||||
pip install crewai
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Get TrueFoundry Access Token">
|
||||
1. Sign up for a [TrueFoundry account](https://www.truefoundry.com/register)
|
||||
2. Follow the steps here in [Quick start](https://docs.truefoundry.com/gateway/quick-start)
|
||||
</Step>
|
||||
|
||||
<Step title="Configure CrewAI with TrueFoundry">
|
||||

|
||||
|
||||
```python
|
||||
from crewai import LLM
|
||||
|
||||
# Create an LLM instance with TrueFoundry AI Gateway
|
||||
truefoundry_llm = LLM(
|
||||
model="openai-main/gpt-4o", # Similarly, you can call any model from any provider
|
||||
base_url="your_truefoundry_gateway_base_url",
|
||||
api_key="your_truefoundry_api_key"
|
||||
)
|
||||
|
||||
# Use in your CrewAI agents
|
||||
from crewai import Agent
|
||||
|
||||
@agent
|
||||
def researcher(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['researcher'],
|
||||
llm=truefoundry_llm,
|
||||
verbose=True
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Complete CrewAI Example
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew, LLM
|
||||
|
||||
# Configure LLM with TrueFoundry
|
||||
llm = LLM(
|
||||
model="openai-main/gpt-4o",
|
||||
base_url="your_truefoundry_gateway_base_url",
|
||||
api_key="your_truefoundry_api_key"
|
||||
)
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
role='Research Analyst',
|
||||
goal='Conduct detailed market research',
|
||||
backstory='Expert market analyst with attention to detail',
|
||||
llm=llm,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
role='Content Writer',
|
||||
goal='Create comprehensive reports',
|
||||
backstory='Experienced technical writer',
|
||||
llm=llm,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
research_task = Task(
|
||||
description='Research AI market trends for 2024',
|
||||
agent=researcher,
|
||||
expected_output='Comprehensive research summary'
|
||||
)
|
||||
|
||||
writing_task = Task(
|
||||
description='Create a market research report',
|
||||
agent=writer,
|
||||
expected_output='Well-structured report with insights',
|
||||
context=[research_task]
|
||||
)
|
||||
|
||||
# Create and execute crew
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[research_task, writing_task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
result = crew.kickoff()
|
||||
```
|
||||
|
||||
### Observability and Governance
|
||||
|
||||
Monitor your CrewAI agents through TrueFoundry's metrics tab:
|
||||

|
||||
|
||||
With Truefoundry's AI gateway, you can monitor and analyze:
|
||||
|
||||
- **Performance Metrics**: Track key latency metrics like Request Latency, Time to First Token (TTFS), and Inter-Token Latency (ITL) with P99, P90, and P50 percentiles
|
||||
- **Cost and Token Usage**: Gain visibility into your application's costs with detailed breakdowns of input/output tokens and the associated expenses for each model
|
||||
- **Usage Patterns**: Understand how your application is being used with detailed analytics on user activity, model distribution, and team-based usage
|
||||
- **Rate limit and Load balancing**: You can set up rate limiting, load balancing and fallback for your models
|
||||
|
||||
## Tracing
|
||||
|
||||
For a more detailed understanding on tracing, please see [getting-started-tracing](https://docs.truefoundry.com/docs/tracing/tracing-getting-started).For tracing, you can add the Traceloop SDK:
|
||||
For tracing, you can add the Traceloop SDK:
|
||||
|
||||
```bash
|
||||
pip install traceloop-sdk
|
||||
```
|
||||
|
||||
```python
|
||||
from traceloop.sdk import Traceloop
|
||||
|
||||
# Initialize enhanced tracing
|
||||
Traceloop.init(
|
||||
api_endpoint="https://your-truefoundry-endpoint/api/tracing",
|
||||
headers={
|
||||
"Authorization": f"Bearer {your_truefoundry_pat_token}",
|
||||
"TFY-Tracing-Project": "your_project_name",
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
This provides additional trace correlation across your entire CrewAI workflow.
|
||||

|
||||
@@ -1,435 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: CrewAI Enterprise API
|
||||
description: |
|
||||
REST API for interacting with your deployed CrewAI crews on CrewAI Enterprise.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Find your crew URL**: Get your unique crew URL from the CrewAI Enterprise dashboard
|
||||
2. **Copy examples**: Use the code examples from each endpoint page as templates
|
||||
3. **Replace placeholders**: Update URLs and tokens with your actual values
|
||||
4. **Test with your tools**: Use cURL, Postman, or your preferred API client
|
||||
|
||||
## Authentication
|
||||
|
||||
All API requests require a bearer token for authentication. There are two types of tokens:
|
||||
|
||||
- **Bearer Token**: Organization-level token for full crew operations
|
||||
- **User Bearer Token**: User-scoped token for individual access with limited permissions
|
||||
|
||||
You can find your bearer tokens in the Status tab of your crew's detail page in the CrewAI Enterprise dashboard.
|
||||
|
||||
## Reference Documentation
|
||||
|
||||
This documentation provides comprehensive examples for each endpoint:
|
||||
|
||||
- **Request formats** with all required and optional parameters
|
||||
- **Response examples** for success and error scenarios
|
||||
- **Code samples** in multiple programming languages
|
||||
- **Authentication patterns** with proper Bearer token usage
|
||||
|
||||
Copy the examples and customize them with your actual crew URL and authentication tokens.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Discover inputs** using `GET /inputs`
|
||||
2. **Start execution** using `POST /kickoff`
|
||||
3. **Monitor progress** using `GET /status/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Support
|
||||
email: support@crewai.com
|
||||
url: https://crewai.com
|
||||
servers:
|
||||
- url: https://your-actual-crew-name.crewai.com
|
||||
description: Replace with your actual deployed crew URL from the CrewAI Enterprise dashboard
|
||||
- url: https://my-travel-crew.crewai.com
|
||||
description: Example travel planning crew (replace with your URL)
|
||||
- url: https://content-creation-crew.crewai.com
|
||||
description: Example content creation crew (replace with your URL)
|
||||
- url: https://research-assistant-crew.crewai.com
|
||||
description: Example research assistant crew (replace with your URL)
|
||||
security:
|
||||
- BearerAuth: []
|
||||
paths:
|
||||
/inputs:
|
||||
get:
|
||||
summary: Get Required Inputs
|
||||
description: |
|
||||
**📋 Reference Example Only** - *This shows the request format. To test with your actual crew, copy the cURL example and replace the URL + token with your real values.*
|
||||
|
||||
Retrieves the list of all required input parameters that your crew expects for execution.
|
||||
Use this endpoint to discover what inputs you need to provide when starting a crew execution.
|
||||
operationId: getRequiredInputs
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully retrieved required inputs
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Array of required input parameter names
|
||||
example: ["budget", "interests", "duration", "age"]
|
||||
examples:
|
||||
travel_crew:
|
||||
summary: Travel planning crew inputs
|
||||
value:
|
||||
inputs: ["budget", "interests", "duration", "age"]
|
||||
outreach_crew:
|
||||
summary: Outreach crew inputs
|
||||
value:
|
||||
inputs: ["name", "title", "company", "industry", "our_product", "linkedin_url"]
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/kickoff:
|
||||
post:
|
||||
summary: Start Crew Execution
|
||||
description: |
|
||||
**📋 Reference Example Only** - *This shows the request format. To test with your actual crew, copy the cURL example and replace the URL + token with your real values.*
|
||||
|
||||
Initiates a new crew execution with the provided inputs. Returns a kickoff ID that can be used
|
||||
to track the execution progress and retrieve results.
|
||||
|
||||
Crew executions can take anywhere from seconds to minutes depending on their complexity.
|
||||
Consider using webhooks for real-time notifications or implement polling with the status endpoint.
|
||||
operationId: startCrewExecution
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- inputs
|
||||
properties:
|
||||
inputs:
|
||||
type: object
|
||||
description: Key-value pairs of all required inputs for your crew
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
budget: "1000 USD"
|
||||
interests: "games, tech, ai, relaxing hikes, amazing food"
|
||||
duration: "7 days"
|
||||
age: "35"
|
||||
meta:
|
||||
type: object
|
||||
description: Additional metadata to pass to the crew
|
||||
additionalProperties: true
|
||||
example:
|
||||
requestId: "user-request-12345"
|
||||
source: "mobile-app"
|
||||
taskWebhookUrl:
|
||||
type: string
|
||||
format: uri
|
||||
description: Callback URL executed after each task completion
|
||||
example: "https://your-server.com/webhooks/task"
|
||||
stepWebhookUrl:
|
||||
type: string
|
||||
format: uri
|
||||
description: Callback URL executed after each agent thought/action
|
||||
example: "https://your-server.com/webhooks/step"
|
||||
crewWebhookUrl:
|
||||
type: string
|
||||
format: uri
|
||||
description: Callback URL executed when the crew execution completes
|
||||
example: "https://your-server.com/webhooks/crew"
|
||||
examples:
|
||||
travel_planning:
|
||||
summary: Travel planning crew
|
||||
value:
|
||||
inputs:
|
||||
budget: "1000 USD"
|
||||
interests: "games, tech, ai, relaxing hikes, amazing food"
|
||||
duration: "7 days"
|
||||
age: "35"
|
||||
meta:
|
||||
requestId: "travel-req-123"
|
||||
source: "web-app"
|
||||
outreach_campaign:
|
||||
summary: Outreach crew with webhooks
|
||||
value:
|
||||
inputs:
|
||||
name: "John Smith"
|
||||
title: "CTO"
|
||||
company: "TechCorp"
|
||||
industry: "Software"
|
||||
our_product: "AI Development Platform"
|
||||
linkedin_url: "https://linkedin.com/in/johnsmith"
|
||||
taskWebhookUrl: "https://api.example.com/webhooks/task"
|
||||
crewWebhookUrl: "https://api.example.com/webhooks/crew"
|
||||
responses:
|
||||
'200':
|
||||
description: Crew execution started successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
kickoff_id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier for tracking this execution
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
'400':
|
||||
description: Invalid request body or missing required inputs
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'422':
|
||||
description: Validation error - ensure all required inputs are provided
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: Get Execution Status
|
||||
description: |
|
||||
**📋 Reference Example Only** - *This shows the request format. To test with your actual crew, copy the cURL example and replace the URL + token with your real values.*
|
||||
|
||||
Retrieves the current status and results of a crew execution using its kickoff ID.
|
||||
|
||||
The response structure varies depending on the execution state:
|
||||
- **running**: Execution in progress with current task info
|
||||
- **completed**: Execution finished with full results
|
||||
- **error**: Execution failed with error details
|
||||
operationId: getExecutionStatus
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
description: The kickoff ID returned from the /kickoff endpoint
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully retrieved execution status
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/ExecutionRunning'
|
||||
- $ref: '#/components/schemas/ExecutionCompleted'
|
||||
- $ref: '#/components/schemas/ExecutionError'
|
||||
examples:
|
||||
running:
|
||||
summary: Execution in progress
|
||||
value:
|
||||
status: "running"
|
||||
current_task: "research_task"
|
||||
progress:
|
||||
completed_tasks: 1
|
||||
total_tasks: 3
|
||||
completed:
|
||||
summary: Execution completed successfully
|
||||
value:
|
||||
status: "completed"
|
||||
result:
|
||||
output: "Comprehensive travel itinerary for 7 days in Japan focusing on tech culture..."
|
||||
tasks:
|
||||
- task_id: "research_task"
|
||||
output: "Research findings on tech destinations in Japan..."
|
||||
agent: "Travel Researcher"
|
||||
execution_time: 45.2
|
||||
- task_id: "planning_task"
|
||||
output: "7-day detailed itinerary with activities and recommendations..."
|
||||
agent: "Trip Planner"
|
||||
execution_time: 62.8
|
||||
execution_time: 108.5
|
||||
error:
|
||||
summary: Execution failed
|
||||
value:
|
||||
status: "error"
|
||||
error: "Task execution failed: Invalid API key for external service"
|
||||
execution_time: 23.1
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
description: Kickoff ID not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
example:
|
||||
error: "Execution not found"
|
||||
message: "No execution found with ID: abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
description: |
|
||||
**📋 Reference Documentation** - *The tokens shown in examples are placeholders for reference only.*
|
||||
|
||||
Use your actual Bearer Token or User Bearer Token from the CrewAI Enterprise dashboard for real API calls.
|
||||
|
||||
**Bearer Token**: Organization-level access for full crew operations
|
||||
**User Bearer Token**: User-scoped access with limited permissions
|
||||
|
||||
schemas:
|
||||
ExecutionRunning:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["running"]
|
||||
example: "running"
|
||||
current_task:
|
||||
type: string
|
||||
description: Name of the currently executing task
|
||||
example: "research_task"
|
||||
progress:
|
||||
type: object
|
||||
properties:
|
||||
completed_tasks:
|
||||
type: integer
|
||||
description: Number of completed tasks
|
||||
example: 1
|
||||
total_tasks:
|
||||
type: integer
|
||||
description: Total number of tasks in the crew
|
||||
example: 3
|
||||
|
||||
ExecutionCompleted:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["completed"]
|
||||
example: "completed"
|
||||
result:
|
||||
type: object
|
||||
properties:
|
||||
output:
|
||||
type: string
|
||||
description: Final output from the crew execution
|
||||
example: "Comprehensive travel itinerary..."
|
||||
tasks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskResult'
|
||||
execution_time:
|
||||
type: number
|
||||
description: Total execution time in seconds
|
||||
example: 108.5
|
||||
|
||||
ExecutionError:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["error"]
|
||||
example: "error"
|
||||
error:
|
||||
type: string
|
||||
description: Error message describing what went wrong
|
||||
example: "Task execution failed: Invalid API key"
|
||||
execution_time:
|
||||
type: number
|
||||
description: Time until error occurred in seconds
|
||||
example: 23.1
|
||||
|
||||
TaskResult:
|
||||
type: object
|
||||
properties:
|
||||
task_id:
|
||||
type: string
|
||||
description: Unique identifier for the task
|
||||
example: "research_task"
|
||||
output:
|
||||
type: string
|
||||
description: Output generated by this task
|
||||
example: "Research findings..."
|
||||
agent:
|
||||
type: string
|
||||
description: Name of the agent that executed this task
|
||||
example: "Travel Researcher"
|
||||
execution_time:
|
||||
type: number
|
||||
description: Time taken to execute this task in seconds
|
||||
example: 45.2
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
description: Error type or title
|
||||
example: "Authentication Error"
|
||||
message:
|
||||
type: string
|
||||
description: Detailed error message
|
||||
example: "Invalid bearer token provided"
|
||||
|
||||
ValidationError:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Validation Error"
|
||||
message:
|
||||
type: string
|
||||
example: "Missing required inputs"
|
||||
details:
|
||||
type: object
|
||||
properties:
|
||||
missing_inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: ["budget", "interests"]
|
||||
|
||||
responses:
|
||||
UnauthorizedError:
|
||||
description: Authentication failed - check your bearer token
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
example:
|
||||
error: "Unauthorized"
|
||||
message: "Invalid or missing bearer token"
|
||||
|
||||
NotFoundError:
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
example:
|
||||
error: "Not Found"
|
||||
message: "The requested resource was not found"
|
||||
|
||||
ServerError:
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
example:
|
||||
error: "Internal Server Error"
|
||||
message: "An unexpected error occurred"
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: CrewAI 엔터프라이즈 API
|
||||
description: |
|
||||
CrewAI Enterprise에 배포된 crew와 상호작용하기 위한 REST API입니다.
|
||||
|
||||
## 시작하기
|
||||
1. **Crew URL 확인**: 대시보드에서 고유한 crew URL을 확인하세요
|
||||
2. **예제 복사**: 각 엔드포인트의 예제를 템플릿으로 사용하세요
|
||||
3. **플레이스홀더 교체**: 실제 URL과 토큰으로 바꾸세요
|
||||
4. **도구로 테스트**: cURL, Postman 등 선호하는 도구로 테스트하세요
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI 지원
|
||||
email: support@crewai.com
|
||||
url: https://crewai.com
|
||||
servers:
|
||||
- url: https://your-actual-crew-name.crewai.com
|
||||
description: 대시보드의 실제 crew URL로 교체하세요
|
||||
security:
|
||||
- BearerAuth: []
|
||||
paths:
|
||||
/inputs:
|
||||
get:
|
||||
summary: 필요 입력값 조회
|
||||
description: |
|
||||
**📋 참조 예제만 제공** - *요청 형식을 보여줍니다. 실제 호출은 cURL 예제를 복사해 URL과 토큰을 교체하세요.*
|
||||
|
||||
실행에 필요한 입력 파라미터 목록을 반환합니다.
|
||||
operationId: getRequiredInputs
|
||||
responses:
|
||||
'200':
|
||||
description: 입력값을 성공적으로 조회
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/kickoff:
|
||||
post:
|
||||
summary: Crew 실행 시작
|
||||
description: |
|
||||
**📋 참조 예제만 제공** - *요청 형식을 보여줍니다. 실제 호출은 cURL 예제를 복사해 URL과 토큰을 교체하세요.*
|
||||
|
||||
제공된 입력으로 새로운 실행을 시작하고 kickoff ID를 반환합니다.
|
||||
operationId: startCrewExecution
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- inputs
|
||||
properties:
|
||||
inputs:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: 실행이 성공적으로 시작됨
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
kickoff_id:
|
||||
type: string
|
||||
format: uuid
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: 실행 상태 조회
|
||||
description: |
|
||||
**📋 참조 예제만 제공** - *요청 형식을 보여줍니다. 실제 호출은 cURL 예제를 복사해 URL과 토큰을 교체하세요.*
|
||||
|
||||
kickoff ID로 실행 상태와 결과를 조회합니다.
|
||||
operationId: getExecutionStatus
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: 상태를 성공적으로 조회
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/ExecutionRunning'
|
||||
- $ref: '#/components/schemas/ExecutionCompleted'
|
||||
- $ref: '#/components/schemas/ExecutionError'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
description: Kickoff ID를 찾을 수 없음
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
description: |
|
||||
**📋 참고** - *예시의 토큰은 자리 표시자입니다.* 실제 토큰을 사용하세요.
|
||||
|
||||
schemas:
|
||||
ExecutionRunning:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["running"]
|
||||
current_task:
|
||||
type: string
|
||||
progress:
|
||||
type: object
|
||||
properties:
|
||||
completed_tasks:
|
||||
type: integer
|
||||
total_tasks:
|
||||
type: integer
|
||||
|
||||
ExecutionCompleted:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["completed"]
|
||||
result:
|
||||
type: object
|
||||
properties:
|
||||
output:
|
||||
type: string
|
||||
tasks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskResult'
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
ExecutionError:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["error"]
|
||||
error:
|
||||
type: string
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
TaskResult:
|
||||
type: object
|
||||
properties:
|
||||
task_id:
|
||||
type: string
|
||||
output:
|
||||
type: string
|
||||
agent:
|
||||
type: string
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
|
||||
ValidationError:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
properties:
|
||||
missing_inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
responses:
|
||||
UnauthorizedError:
|
||||
description: 인증 실패
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
NotFoundError:
|
||||
description: 리소스를 찾을 수 없음
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
ServerError:
|
||||
description: 서버 내부 오류
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
@@ -1,268 +0,0 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: CrewAI Enterprise API
|
||||
description: |
|
||||
REST API para interagir com suas crews implantadas no CrewAI Enterprise.
|
||||
|
||||
## Introdução
|
||||
|
||||
1. **Encontre a URL da sua crew**: Obtenha sua URL única no painel do CrewAI Enterprise
|
||||
2. **Copie os exemplos**: Use os exemplos de cada endpoint como modelo
|
||||
3. **Substitua os placeholders**: Atualize URLs e tokens com seus valores reais
|
||||
4. **Teste com suas ferramentas**: Use cURL, Postman ou seu cliente preferido
|
||||
|
||||
## Autenticação
|
||||
|
||||
Todas as requisições exigem um token bearer. Existem dois tipos:
|
||||
|
||||
- **Bearer Token**: Token em nível de organização para operações completas
|
||||
- **User Bearer Token**: Token com escopo de usuário com permissões limitadas
|
||||
|
||||
Você encontra os tokens na aba Status da sua crew no painel do CrewAI Enterprise.
|
||||
|
||||
## Documentação de Referência
|
||||
|
||||
Este documento fornece exemplos completos para cada endpoint:
|
||||
|
||||
- **Formatos de requisição** com parâmetros obrigatórios e opcionais
|
||||
- **Exemplos de resposta** para sucesso e erro
|
||||
- **Amostras de código** em várias linguagens
|
||||
- **Padrões de autenticação** com uso correto de Bearer token
|
||||
|
||||
Copie os exemplos e personalize com sua URL e tokens reais.
|
||||
|
||||
## Fluxo
|
||||
|
||||
1. **Descubra os inputs** usando `GET /inputs`
|
||||
2. **Inicie a execução** usando `POST /kickoff`
|
||||
3. **Monitore o progresso** usando `GET /status/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Suporte
|
||||
email: support@crewai.com
|
||||
url: https://crewai.com
|
||||
servers:
|
||||
- url: https://your-actual-crew-name.crewai.com
|
||||
description: Substitua pela URL real da sua crew no painel do CrewAI Enterprise
|
||||
security:
|
||||
- BearerAuth: []
|
||||
paths:
|
||||
/inputs:
|
||||
get:
|
||||
summary: Obter Inputs Requeridos
|
||||
description: |
|
||||
**📋 Exemplo de Referência** - *Mostra o formato da requisição. Para testar com sua crew real, copie o cURL e substitua URL + token.*
|
||||
|
||||
Retorna a lista de parâmetros de entrada que sua crew espera.
|
||||
operationId: getRequiredInputs
|
||||
responses:
|
||||
'200':
|
||||
description: Inputs requeridos obtidos com sucesso
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Nomes dos parâmetros de entrada
|
||||
example: ["budget", "interests", "duration", "age"]
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFoundError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/kickoff:
|
||||
post:
|
||||
summary: Iniciar Execução da Crew
|
||||
description: |
|
||||
**📋 Exemplo de Referência** - *Mostra o formato da requisição. Para testar com sua crew real, copie o cURL e substitua URL + token.*
|
||||
|
||||
Inicia uma nova execução da crew com os inputs fornecidos e retorna um kickoff ID.
|
||||
operationId: startCrewExecution
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- inputs
|
||||
properties:
|
||||
inputs:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
budget: "1000 USD"
|
||||
interests: "games, tech, ai, relaxing hikes, amazing food"
|
||||
duration: "7 days"
|
||||
age: "35"
|
||||
|
||||
responses:
|
||||
'200':
|
||||
description: Execução iniciada com sucesso
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
kickoff_id:
|
||||
type: string
|
||||
format: uuid
|
||||
example: "abcd1234-5678-90ef-ghij-klmnopqrstuv"
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: Obter Status da Execução
|
||||
description: |
|
||||
**📋 Exemplo de Referência** - *Mostra o formato da requisição. Para testar com sua crew real, copie o cURL e substitua URL + token.*
|
||||
|
||||
Retorna o status atual e os resultados de uma execução usando o kickoff ID.
|
||||
operationId: getExecutionStatus
|
||||
parameters:
|
||||
- name: kickoff_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: Status recuperado com sucesso
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/ExecutionRunning'
|
||||
- $ref: '#/components/schemas/ExecutionCompleted'
|
||||
- $ref: '#/components/schemas/ExecutionError'
|
||||
'401':
|
||||
$ref: '#/components/responses/UnauthorizedError'
|
||||
'404':
|
||||
description: Kickoff ID não encontrado
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
description: |
|
||||
**📋 Referência** - *Os tokens mostrados são apenas exemplos.*
|
||||
Use seus tokens reais do painel do CrewAI Enterprise.
|
||||
|
||||
schemas:
|
||||
ExecutionRunning:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["running"]
|
||||
current_task:
|
||||
type: string
|
||||
progress:
|
||||
type: object
|
||||
properties:
|
||||
completed_tasks:
|
||||
type: integer
|
||||
total_tasks:
|
||||
type: integer
|
||||
|
||||
ExecutionCompleted:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["completed"]
|
||||
result:
|
||||
type: object
|
||||
properties:
|
||||
output:
|
||||
type: string
|
||||
tasks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskResult'
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
ExecutionError:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: ["error"]
|
||||
error:
|
||||
type: string
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
TaskResult:
|
||||
type: object
|
||||
properties:
|
||||
task_id:
|
||||
type: string
|
||||
output:
|
||||
type: string
|
||||
agent:
|
||||
type: string
|
||||
execution_time:
|
||||
type: number
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
|
||||
ValidationError:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
properties:
|
||||
missing_inputs:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
responses:
|
||||
UnauthorizedError:
|
||||
description: Autenticação falhou
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
NotFoundError:
|
||||
description: Recurso não encontrado
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
ServerError:
|
||||
description: Erro interno do servidor
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 248 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 472 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 530 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 554 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 128 KiB |
@@ -1,103 +0,0 @@
|
||||
---
|
||||
title: "역할 기반 접근 제어 (RBAC)"
|
||||
description: "역할과 자동화별 가시성으로 crews, 도구, 데이터 접근을 제어합니다."
|
||||
icon: "shield"
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
CrewAI Enterprise의 RBAC는 **조직 수준 역할**과 **자동화(Automation) 수준 가시성**을 결합하여 안전하고 확장 가능한 접근 제어를 제공합니다.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/users_and_roles.png" alt="CrewAI Enterprise RBAC 개요" />
|
||||
|
||||
</Frame>
|
||||
|
||||
## 사용자와 역할
|
||||
|
||||
워크스페이스의 각 구성원은 역할이 있으며, 이는 기능 접근 범위를 결정합니다.
|
||||
|
||||
가능한 작업:
|
||||
|
||||
- 사전 정의된 역할 사용 (Owner, Member)
|
||||
- 권한을 세분화한 커스텀 역할 생성
|
||||
- 설정 화면에서 언제든 역할 할당/변경
|
||||
|
||||
설정 위치: Settings → Roles
|
||||
|
||||
<Steps>
|
||||
<Step title="Roles 열기">
|
||||
<b>Settings → Roles</b>로 이동합니다.
|
||||
</Step>
|
||||
<Step title="역할 선택">
|
||||
<b>Owner</b> 또는 <b>Member</b>를 사용하거나 <b>Create role</b>로 커스텀 역할을 만듭니다.
|
||||
</Step>
|
||||
<Step title="멤버에 할당">
|
||||
사용자들을 선택하여 역할을 지정합니다. 언제든 변경할 수 있습니다.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### 구성 요약
|
||||
|
||||
| 영역 | 위치 | 옵션 |
|
||||
|:---|:---|:---|
|
||||
| 사용자 & 역할 | Settings → Roles | Owner, Member; 커스텀 역할 |
|
||||
| 자동화 가시성 | Automation → Settings → Visibility | Private; 사용자/역할 화이트리스트 |
|
||||
|
||||
## 자동화 수준 접근 제어
|
||||
|
||||
조직 역할과 별개로, **Automations**는 사용자/역할별로 특정 자동화 접근을 제한하는 가시성 설정을 제공합니다.
|
||||
|
||||
유용한 경우:
|
||||
|
||||
- 민감/실험 자동화를 비공개로 유지
|
||||
- 대규모 팀/외부 협업에서 가시성 관리
|
||||
- 격리된 컨텍스트에서 자동화 테스트
|
||||
|
||||
Private 모드에서는 화이트리스트에 포함된 사용자/역할만 다음 작업이 가능합니다:
|
||||
|
||||
- 자동화 보기
|
||||
- 실행/API 사용
|
||||
- 로그, 메트릭, 설정 접근
|
||||
|
||||
조직 Owner는 항상 접근 가능하며, 가시성 설정에 영향을 받지 않습니다.
|
||||
|
||||
설정 위치: Automation → Settings → Visibility
|
||||
|
||||
<Steps>
|
||||
<Step title="Visibility 탭 열기">
|
||||
<b>Automation → Settings → Visibility</b>로 이동합니다.
|
||||
</Step>
|
||||
<Step title="가시성 설정">
|
||||
<b>Private</b>를 선택합니다. Owner는 항상 접근 가능합니다.
|
||||
</Step>
|
||||
<Step title="허용 대상 추가">
|
||||
보기/실행/로그·메트릭·설정 접근이 가능한 사용자/역할을 추가합니다.
|
||||
</Step>
|
||||
<Step title="저장 및 확인">
|
||||
저장 후, 목록에 없는 사용자가 보거나 실행할 수 없는지 확인합니다.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Private 모드 접근 결과
|
||||
|
||||
| 동작 | Owner | 화이트리스트 사용자/역할 | 비포함 |
|
||||
|:---|:---|:---|:---|
|
||||
| 자동화 보기 | ✓ | ✓ | ✗ |
|
||||
| 실행/API | ✓ | ✓ | ✗ |
|
||||
| 로그/메트릭/설정 | ✓ | ✓ | ✗ |
|
||||
|
||||
<Tip>
|
||||
Owner는 항상 접근 가능하며, Private 모드에서는 화이트리스트에 포함된 사용자/역할만 권한이 부여됩니다.
|
||||
</Tip>
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/visibility.png" alt="CrewAI Enterprise 가시성 설정" />
|
||||
|
||||
</Frame>
|
||||
|
||||
<Card title="도움이 필요하신가요?" icon="headset" href="mailto:support@crewai.com">
|
||||
RBAC 구성과 점검에 대한 지원이 필요하면 연락해 주세요.
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: CrewAI Cookbooks
|
||||
description: 패턴을 빠르게 익히기 위한 기능 중심 Quickstarts와 노트북.
|
||||
icon: book
|
||||
---
|
||||
|
||||
## Quickstarts & Demos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstarts 저장소" icon="bolt" href="https://github.com/crewAIInc/crewAI-quickstarts">
|
||||
특정 CrewAI 기능을 보여주는 데모와 소규모 프로젝트.
|
||||
</Card>
|
||||
<Card title="예시의 노트북" icon="book-open" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks">
|
||||
실습을 위한 인터랙티브 노트북.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Cookbooks로 패턴을 빠르게 익힌 뒤, 프로덕션급 구현은 Full Examples에서 확인하세요.
|
||||
</Tip>
|
||||
|
||||
|
||||
@@ -1,85 +1,62 @@
|
||||
---
|
||||
title: CrewAI 예시
|
||||
description: Crews, Flows, 통합, Notebooks로 구성된 예시 모음입니다.
|
||||
description: CrewAI 프레임워크를 사용하여 워크플로우를 자동화하는 방법을 보여주는 예시 모음입니다.
|
||||
icon: rocket-launch
|
||||
---
|
||||
|
||||
## Crews
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="마케팅 전략" icon="bullhorn" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/marketing_strategy">
|
||||
다중 에이전트 마케팅 캠페인 기획.
|
||||
</Card>
|
||||
<Card title="깜짝 여행" icon="plane" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/surprise_trip">
|
||||
개인화된 여행 계획.
|
||||
</Card>
|
||||
<Card title="프로필-포지션 매칭" icon="id-card" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/match_profile_to_positions">
|
||||
벡터 검색 기반 이력서 매칭.
|
||||
</Card>
|
||||
<Card title="채용 공고" icon="newspaper" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/job-posting">
|
||||
채용 공고 자동 생성.
|
||||
</Card>
|
||||
<Card title="게임 빌더 Crew" icon="gamepad" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/game-builder-crew">
|
||||
파이썬 게임을 설계·구축하는 멀티 에이전트 팀.
|
||||
</Card>
|
||||
<Card title="리크루팅" icon="user-group" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/recruitment">
|
||||
후보자 소싱 및 평가.
|
||||
</Card>
|
||||
<Card title="모든 Crews 보기" icon="users" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews">
|
||||
전체 crew 예시 목록.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Flows
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Content Creator Flow" icon="pen" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/content_creator_flow">
|
||||
라우팅 기반 콘텐츠 생성.
|
||||
</Card>
|
||||
<Card title="이메일 자동 응답" icon="envelope" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/email_auto_responder_flow">
|
||||
이메일 모니터링과 자동 응답.
|
||||
</Card>
|
||||
<Card title="리드 점수 Flow" icon="chart-line" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/lead_score_flow">
|
||||
휴먼‑인‑더‑루프 리드 평가.
|
||||
</Card>
|
||||
<Card title="미팅 어시스턴트 Flow" icon="calendar" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/meeting_assistant_flow">
|
||||
노트 처리 및 연동.
|
||||
</Card>
|
||||
<Card title="Self Evaluation Loop" icon="rotate" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/self_evaluation_loop_flow">
|
||||
반복적 자가 개선 워크플로우.
|
||||
</Card>
|
||||
<Card title="책 쓰기 (Flows)" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/write_a_book_with_flows">
|
||||
병렬 챕터 생성.
|
||||
</Card>
|
||||
<Card title="모든 Flows 보기" icon="diagram-project" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows">
|
||||
전체 flow 예시 목록.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 통합 (Integrations)
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="CrewAI ↔ LangGraph" icon="link" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/crewai-langgraph">
|
||||
LangGraph 프레임워크 연동.
|
||||
</Card>
|
||||
<Card title="Azure OpenAI" icon="cloud" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/azure_model">
|
||||
Azure OpenAI와 함께 사용.
|
||||
</Card>
|
||||
<Card title="NVIDIA 모델" icon="microchip" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/nvidia_models">
|
||||
NVIDIA 생태계 연동.
|
||||
</Card>
|
||||
<Card title="모든 통합 보기" icon="puzzle-piece" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations">
|
||||
전체 통합 예시.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 노트북 (Notebooks)
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Simple QA Crew + Flow" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks/Simple%20QA%20Crew%20%2B%20Flow">
|
||||
Simple QA Crew + Flow.
|
||||
</Card>
|
||||
<Card title="모든 노트북" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks">
|
||||
학습과 실험을 위한 인터랙티브 예시 모음.
|
||||
<Card
|
||||
title="마케팅 전략"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/marketing_strategy"
|
||||
icon="bullhorn"
|
||||
iconType="solid"
|
||||
>
|
||||
CrewAI로 마케팅 전략 생성을 자동화하세요.
|
||||
</Card>
|
||||
<Card
|
||||
title="깜짝 여행"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/surprise_trip"
|
||||
icon="plane"
|
||||
iconType="duotone"
|
||||
>
|
||||
CrewAI로 깜짝 여행 일정표를 만들어보세요.
|
||||
</Card>
|
||||
<Card
|
||||
title="프로필과 포지션 매칭"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/match_profile_to_positions"
|
||||
icon="linkedin"
|
||||
iconType="duotone"
|
||||
>
|
||||
CrewAI로 프로필을 채용 포지션에 매칭하세요.
|
||||
</Card>
|
||||
<Card
|
||||
title="채용 공고 생성"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/job-posting"
|
||||
icon="newspaper"
|
||||
iconType="duotone"
|
||||
>
|
||||
CrewAI로 채용 공고를 만드세요.
|
||||
</Card>
|
||||
<Card
|
||||
title="게임 생성기"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/game-builder-crew"
|
||||
icon="gamepad"
|
||||
iconType="duotone"
|
||||
>
|
||||
CrewAI로 게임을 만들어보세요.
|
||||
</Card>
|
||||
<Card
|
||||
title="채용 후보자 찾기"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/recruitment"
|
||||
icon="user-group"
|
||||
iconType="duotone"
|
||||
>
|
||||
CrewAI로 채용 후보자를 찾으세요.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
title: "Controle de Acesso Baseado em Funções (RBAC)"
|
||||
description: "Controle o acesso a crews, ferramentas e dados com funções e visibilidade por automação."
|
||||
icon: "shield"
|
||||
---
|
||||
|
||||
## Visão Geral
|
||||
|
||||
O RBAC no CrewAI Enterprise permite gerenciar acesso de forma segura e escalável combinando **funções em nível de organização** com **controles de visibilidade em nível de automação**.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/users_and_roles.png" alt="Visão geral de RBAC no CrewAI Enterprise" />
|
||||
|
||||
</Frame>
|
||||
|
||||
## Usuários e Funções
|
||||
|
||||
Cada membro da sua workspace possui uma função, que determina o acesso aos recursos.
|
||||
|
||||
Você pode:
|
||||
|
||||
- Usar funções pré-definidas (Owner, Member)
|
||||
- Criar funções personalizadas com permissões específicas
|
||||
- Atribuir funções a qualquer momento no painel de configurações
|
||||
|
||||
A configuração de usuários e funções é feita em Settings → Roles.
|
||||
|
||||
<Steps>
|
||||
<Step title="Abrir Roles">
|
||||
Vá em <b>Settings → Roles</b> no CrewAI Enterprise.
|
||||
</Step>
|
||||
<Step title="Escolher a função">
|
||||
Use <b>Owner</b> ou <b>Member</b>, ou clique em <b>Create role</b> para criar uma função personalizada.
|
||||
</Step>
|
||||
<Step title="Atribuir aos membros">
|
||||
Selecione os usuários e atribua a função. Você pode alterar depois.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Resumo de configuração
|
||||
|
||||
| Área | Onde configurar | Opções |
|
||||
|:---|:---|:---|
|
||||
| Usuários & Funções | Settings → Roles | Pré-definidas: Owner, Member; Funções personalizadas |
|
||||
| Visibilidade da automação | Automation → Settings → Visibility | Private; Lista de usuários/funções |
|
||||
|
||||
## Controle de Acesso em Nível de Automação
|
||||
|
||||
Além das funções na organização, as **Automations** suportam visibilidade refinada para restringir acesso por usuário ou função.
|
||||
|
||||
Útil para:
|
||||
|
||||
- Manter automações sensíveis/experimentais privadas
|
||||
- Gerenciar visibilidade em equipes grandes ou colaboradores externos
|
||||
- Testar automações em contexto isolado
|
||||
|
||||
Em modo privado, somente usuários/funções na whitelist poderão:
|
||||
|
||||
- Ver a automação
|
||||
- Executar/usar a API
|
||||
- Acessar logs, métricas e configurações
|
||||
|
||||
O owner da organização sempre tem acesso, independente da visibilidade.
|
||||
|
||||
Configure em Automation → Settings → Visibility.
|
||||
|
||||
<Steps>
|
||||
<Step title="Abrir a aba Visibility">
|
||||
Acesse <b>Automation → Settings → Visibility</b>.
|
||||
</Step>
|
||||
<Step title="Definir visibilidade">
|
||||
Selecione <b>Private</b> para restringir o acesso. O owner mantém acesso.
|
||||
</Step>
|
||||
<Step title="Permitir acesso">
|
||||
Adicione usuários e funções que poderão ver/executar e acessar logs/métricas/configurações.
|
||||
</Step>
|
||||
<Step title="Salvar e verificar">
|
||||
Salve e confirme que não listados não conseguem ver ou executar a automação.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Resultado de acesso no modo Private
|
||||
|
||||
| Ação | Owner | Usuário/função na whitelist | Não listado |
|
||||
|:---|:---|:---|:---|
|
||||
| Ver automação | ✓ | ✓ | ✗ |
|
||||
| Executar/API | ✓ | ✓ | ✗ |
|
||||
| Logs/métricas/configurações | ✓ | ✓ | ✗ |
|
||||
|
||||
<Tip>
|
||||
O owner sempre possui acesso. Em modo privado, somente usuários/funções na whitelist têm permissão.
|
||||
</Tip>
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/visibility.png" alt="Configuração de visibilidade no CrewAI Enterprise" />
|
||||
|
||||
</Frame>
|
||||
|
||||
<Card title="Precisa de Ajuda?" icon="headset" href="mailto:support@crewai.com">
|
||||
Fale com o nosso time para suporte em configuração e auditoria de RBAC.
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: CrewAI Cookbooks
|
||||
description: Quickstarts e notebooks focados em recursos para aprender padrões rapidamente.
|
||||
icon: book
|
||||
---
|
||||
|
||||
## Quickstarts & Demos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Repositório de Quickstarts" icon="bolt" href="https://github.com/crewAIInc/crewAI-quickstarts">
|
||||
Demos e projetos pequenos que mostram capacidades específicas do CrewAI.
|
||||
</Card>
|
||||
<Card title="Notebooks nos Exemplos" icon="book-open" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks">
|
||||
Notebooks interativos para aprendizado prático.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Use Cookbooks para aprender um padrão rapidamente e, em seguida, avance para os Exemplos completos para implementações de produção.
|
||||
</Tip>
|
||||
|
||||
|
||||
@@ -1,85 +1,62 @@
|
||||
---
|
||||
title: Exemplos CrewAI
|
||||
description: Explore exemplos organizados por Crews, Flows, Integrações e Notebooks.
|
||||
description: Uma coleção de exemplos que mostram como usar o framework CrewAI para automatizar fluxos de trabalho.
|
||||
icon: rocket-launch
|
||||
---
|
||||
|
||||
## Crews
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Estratégia de Marketing" icon="bullhorn" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/marketing_strategy">
|
||||
Planejamento de campanhas com múltiplos agentes.
|
||||
</Card>
|
||||
<Card title="Viagem Surpresa" icon="plane" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/surprise_trip">
|
||||
Planejamento de viagens personalizadas.
|
||||
</Card>
|
||||
<Card title="Relacionar Perfil a Posições" icon="id-card" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/match_profile_to_positions">
|
||||
Correspondência de CV para vagas com busca vetorial.
|
||||
</Card>
|
||||
<Card title="Criar Vaga" icon="newspaper" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/job-posting">
|
||||
Criação automatizada de descrições de vagas.
|
||||
</Card>
|
||||
<Card title="Crew Construtor de Jogos" icon="gamepad" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/game-builder-crew">
|
||||
Equipe multiagente que projeta e constrói jogos em Python.
|
||||
</Card>
|
||||
<Card title="Recrutamento" icon="user-group" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews/recruitment">
|
||||
Prospecção e avaliação de candidatos.
|
||||
</Card>
|
||||
<Card title="Ver todos os Crews" icon="users" href="https://github.com/crewAIInc/crewAI-examples/tree/main/crews">
|
||||
Lista completa de exemplos de crews.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Flows
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Content Creator Flow" icon="pen" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/content_creator_flow">
|
||||
Geração de conteúdo com roteamento.
|
||||
</Card>
|
||||
<Card title="Email Auto Responder" icon="envelope" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/email_auto_responder_flow">
|
||||
Monitoramento e respostas de e‑mail.
|
||||
</Card>
|
||||
<Card title="Lead Score Flow" icon="chart-line" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/lead_score_flow">
|
||||
Qualificação de leads com revisão humana.
|
||||
</Card>
|
||||
<Card title="Meeting Assistant Flow" icon="calendar" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/meeting_assistant_flow">
|
||||
Processamento de notas com integrações.
|
||||
</Card>
|
||||
<Card title="Self Evaluation Loop" icon="rotate" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/self_evaluation_loop_flow">
|
||||
Fluxos de autoaperfeiçoamento iterativo.
|
||||
</Card>
|
||||
<Card title="Escrever um Livro (Flows)" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows/write_a_book_with_flows">
|
||||
Geração paralela de capítulos.
|
||||
</Card>
|
||||
<Card title="Ver todos os Flows" icon="diagram-project" href="https://github.com/crewAIInc/crewAI-examples/tree/main/flows">
|
||||
Lista completa de exemplos de flows.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Integrações
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="CrewAI ↔ LangGraph" icon="link" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/crewai-langgraph">
|
||||
Integração com o framework LangGraph.
|
||||
</Card>
|
||||
<Card title="Azure OpenAI" icon="cloud" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/azure_model">
|
||||
Usando CrewAI com Azure OpenAI.
|
||||
</Card>
|
||||
<Card title="Modelos NVIDIA" icon="microchip" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations/nvidia_models">
|
||||
Integrações com o ecossistema NVIDIA.
|
||||
</Card>
|
||||
<Card title="Ver todas as Integrações" icon="puzzle-piece" href="https://github.com/crewAIInc/crewAI-examples/tree/main/integrations">
|
||||
Todos os exemplos de integrações.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Notebooks
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Simple QA Crew + Flow" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks/Simple%20QA%20Crew%20%2B%20Flow">
|
||||
Simple QA Crew + Flow.
|
||||
</Card>
|
||||
<Card title="Todos os Notebooks" icon="book" href="https://github.com/crewAIInc/crewAI-examples/tree/main/Notebooks">
|
||||
Exemplos interativos para aprendizado e experimentação.
|
||||
<Card
|
||||
title="Estratégia de Marketing"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/marketing_strategy"
|
||||
icon="bullhorn"
|
||||
iconType="solid"
|
||||
>
|
||||
Automatize a criação de estratégias de marketing com CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Viagem Surpresa"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/surprise_trip"
|
||||
icon="plane"
|
||||
iconType="duotone"
|
||||
>
|
||||
Crie um roteiro de viagem surpresa com CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Relacionar Perfil a Posições"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/match_profile_to_positions"
|
||||
icon="linkedin"
|
||||
iconType="duotone"
|
||||
>
|
||||
Relacione um perfil a vagas de emprego com CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Criar Vaga"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/job-posting"
|
||||
icon="newspaper"
|
||||
iconType="duotone"
|
||||
>
|
||||
Crie uma vaga de emprego com CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Gerador de Jogos"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/game-builder-crew"
|
||||
icon="gamepad"
|
||||
iconType="duotone"
|
||||
>
|
||||
Crie um jogo com CrewAI.
|
||||
</Card>
|
||||
<Card
|
||||
title="Encontrar Candidatos"
|
||||
color="#F3A78B"
|
||||
href="https://github.com/crewAIInc/crewAI-examples/tree/main/recruitment"
|
||||
icon="user-group"
|
||||
iconType="duotone"
|
||||
>
|
||||
Encontre candidatos a vagas com CrewAI.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,145 +0,0 @@
|
||||
---
|
||||
title: Integração com a TrueFoundry
|
||||
icon: chart-line
|
||||
---
|
||||
|
||||
A TrueFoundry fornece um [AI Gateway](https://www.truefoundry.com/ai-gateway) pronto para uso empresarial, que pode ser usado para governança e observabilidade em frameworks agentivos como o CrewAI. O AI Gateway da TrueFoundry funciona como uma interface unificada para acesso a LLMs, oferecendo:
|
||||
|
||||
- **Acesso unificado à API**: Conecte-se a 250+ LLMs (OpenAI, Claude, Gemini, Groq, Mistral) por meio de uma única API
|
||||
- **Baixa latência**: Latência interna abaixo de 3 ms com roteamento inteligente e balanceamento de carga
|
||||
- **Segurança corporativa**: Conformidade com SOC 2, HIPAA e GDPR, com RBAC e auditoria de logs
|
||||
- **Gestão de cotas e custos**: Cotas baseadas em tokens, rate limiting e rastreamento abrangente de uso
|
||||
- **Observabilidade**: Registro completo de requisições/respostas, métricas e traces com retenção personalizável
|
||||
|
||||
## Como a TrueFoundry se integra ao CrewAI
|
||||
|
||||
|
||||
### Instalação e configuração
|
||||
|
||||
<Steps>
|
||||
<Step title="Instalar o CrewAI">
|
||||
```bash
|
||||
pip install crewai
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Obter o token de acesso da TrueFoundry">
|
||||
1. Crie uma conta na [TrueFoundry](https://www.truefoundry.com/register)
|
||||
2. Siga os passos do [Início rápido](https://docs.truefoundry.com/gateway/quick-start)
|
||||
</Step>
|
||||
|
||||
<Step title="Configurar o CrewAI com a TrueFoundry">
|
||||

|
||||
|
||||
```python
|
||||
from crewai import LLM
|
||||
|
||||
# Criar uma instância de LLM com o AI Gateway da TrueFoundry
|
||||
truefoundry_llm = LLM(
|
||||
model="openai-main/gpt-4o", # Da mesma forma, você pode chamar qualquer modelo de qualquer provedor
|
||||
base_url="your_truefoundry_gateway_base_url",
|
||||
api_key="your_truefoundry_api_key"
|
||||
)
|
||||
|
||||
# Usar nos seus agentes do CrewAI
|
||||
from crewai import Agent
|
||||
|
||||
@agent
|
||||
def researcher(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['researcher'],
|
||||
llm=truefoundry_llm,
|
||||
verbose=True
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Exemplo completo do CrewAI
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew, LLM
|
||||
|
||||
# Configurar o LLM com a TrueFoundry
|
||||
llm = LLM(
|
||||
model="openai-main/gpt-4o",
|
||||
base_url="your_truefoundry_gateway_base_url",
|
||||
api_key="your_truefoundry_api_key"
|
||||
)
|
||||
|
||||
# Criar agentes
|
||||
researcher = Agent(
|
||||
role='Analista de Pesquisa',
|
||||
goal='Conduzir pesquisa de mercado detalhada',
|
||||
backstory='Analista de mercado especialista com atenção aos detalhes',
|
||||
llm=llm,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
role='Redator de Conteúdo',
|
||||
goal='Criar relatórios abrangentes',
|
||||
backstory='Redator técnico experiente',
|
||||
llm=llm,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Criar tarefas
|
||||
research_task = Task(
|
||||
description='Pesquisar tendências do mercado de IA para 2024',
|
||||
agent=researcher,
|
||||
expected_output='Resumo de pesquisa abrangente'
|
||||
)
|
||||
|
||||
writing_task = Task(
|
||||
description='Criar um relatório de pesquisa de mercado',
|
||||
agent=writer,
|
||||
expected_output='Relatório bem estruturado com insights',
|
||||
context=[research_task]
|
||||
)
|
||||
|
||||
# Criar e executar a crew
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[research_task, writing_task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
result = crew.kickoff()
|
||||
```
|
||||
|
||||
### Observabilidade e governança
|
||||
|
||||
Monitore seus agentes do CrewAI pela aba de métricas da TrueFoundry:
|
||||

|
||||
|
||||
Com o AI Gateway da TrueFoundry, você pode monitorar e analisar:
|
||||
|
||||
- **Métricas de desempenho**: Acompanhe métricas-chave de latência como Latência da Requisição, Tempo até o Primeiro Token (TTFS) e Latência entre Tokens (ITL), com percentis P99, P90 e P50
|
||||
- **Custos e uso de tokens**: Tenha visibilidade dos custos da sua aplicação com detalhamento de tokens de entrada/saída e das despesas associadas a cada modelo
|
||||
- **Padrões de uso**: Entenda como sua aplicação está sendo utilizada com análises detalhadas sobre atividade de usuários, distribuição de modelos e uso por equipe
|
||||
- **Limite de taxa e balanceamento de carga**: Você pode configurar rate limiting, balanceamento de carga e fallback para seus modelos
|
||||
|
||||
## Rastreamento
|
||||
|
||||
Para uma compreensão mais detalhada sobre rastreamento, consulte [getting-started-tracing](https://docs.truefoundry.com/docs/tracing/tracing-getting-started). Para rastreamento, você pode adicionar o SDK do Traceloop:
|
||||
|
||||
```bash
|
||||
pip install traceloop-sdk
|
||||
```
|
||||
|
||||
```python
|
||||
from traceloop.sdk import Traceloop
|
||||
|
||||
# Inicializar rastreamento avançado
|
||||
Traceloop.init(
|
||||
api_endpoint="https://your-truefoundry-endpoint/api/tracing",
|
||||
headers={
|
||||
"Authorization": f"Bearer {your_truefoundry_pat_token}",
|
||||
"TFY-Tracing-Project": "your_project_name",
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
Isso oferece correlação adicional de rastreamentos em todo o seu fluxo de trabalho com o CrewAI.
|
||||

|
||||
@@ -48,7 +48,7 @@ Documentation = "https://docs.crewai.com"
|
||||
Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tools = ["crewai-tools~=0.62.0"]
|
||||
tools = ["crewai-tools~=0.60.0"]
|
||||
embeddings = [
|
||||
"tiktoken~=0.8.0"
|
||||
]
|
||||
|
||||
57
simple_test_verbose.py
Normal file
57
simple_test_verbose.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Simple test to verify the verbose task name fix works."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
||||
|
||||
from unittest.mock import Mock
|
||||
from crewai.utilities.events.utils.console_formatter import ConsoleFormatter
|
||||
|
||||
def test_task_display_name():
|
||||
"""Test the _get_task_display_name method directly."""
|
||||
print("Testing _get_task_display_name method...")
|
||||
|
||||
formatter = ConsoleFormatter(verbose=True)
|
||||
|
||||
task1 = Mock()
|
||||
task1.name = "Research Market Trends"
|
||||
task1.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
result1 = formatter._get_task_display_name(task1)
|
||||
print(f"Test 1 - Task with name: {result1}")
|
||||
assert "Research Market Trends" in result1
|
||||
assert "12345678" in result1
|
||||
print("✅ Test 1 passed")
|
||||
|
||||
task2 = Mock()
|
||||
task2.name = None
|
||||
task2.description = "Analyze current market trends and provide insights"
|
||||
task2.id = "87654321-4321-8765-2109-987654321abc"
|
||||
|
||||
result2 = formatter._get_task_display_name(task2)
|
||||
print(f"Test 2 - Task with description: {result2}")
|
||||
assert "Analyze current market trends" in result2
|
||||
assert "87654321" in result2
|
||||
print("✅ Test 2 passed")
|
||||
|
||||
task3 = Mock()
|
||||
task3.name = None
|
||||
task3.description = None
|
||||
task3.id = "abcdef12-3456-7890-abcd-ef1234567890"
|
||||
|
||||
result3 = formatter._get_task_display_name(task3)
|
||||
print(f"Test 3 - Task with ID only: {result3}")
|
||||
assert result3 == "abcdef12-3456-7890-abcd-ef1234567890"
|
||||
print("✅ Test 3 passed")
|
||||
|
||||
print("\n🎉 All tests passed! The verbose task name fix is working correctly.")
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_task_display_name()
|
||||
print("\n✅ Implementation verified successfully!")
|
||||
except Exception as e:
|
||||
print(f"\n❌ Test failed: {e}")
|
||||
sys.exit(1)
|
||||
@@ -54,7 +54,7 @@ def _track_install_async():
|
||||
|
||||
_track_install_async()
|
||||
|
||||
__version__ = "0.159.0"
|
||||
__version__ = "0.157.0"
|
||||
__all__ = [
|
||||
"Agent",
|
||||
"Crew",
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.159.0,<1.0.0"
|
||||
"crewai[tools]>=0.157.0,<1.0.0"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.159.0,<1.0.0",
|
||||
"crewai[tools]>=0.157.0,<1.0.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "Power up your crews with {{folder_name}}"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]>=0.159.0"
|
||||
"crewai[tools]>=0.157.0"
|
||||
]
|
||||
|
||||
[tool.crewai]
|
||||
|
||||
@@ -17,13 +17,10 @@ from typing import (
|
||||
)
|
||||
from uuid import uuid4
|
||||
|
||||
from opentelemetry import baggage
|
||||
from opentelemetry.context import attach, detach
|
||||
from pydantic import BaseModel, Field, ValidationError
|
||||
|
||||
from crewai.flow.flow_visualizer import plot_flow
|
||||
from crewai.flow.persistence.base import FlowPersistence
|
||||
from crewai.flow.types import FlowExecutionData
|
||||
from crewai.flow.utils import get_possible_return_constants
|
||||
from crewai.utilities.events.crewai_event_bus import crewai_event_bus
|
||||
from crewai.utilities.events.flow_events import (
|
||||
@@ -470,7 +467,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
self._method_execution_counts: Dict[str, int] = {}
|
||||
self._pending_and_listeners: Dict[str, Set[str]] = {}
|
||||
self._method_outputs: List[Any] = [] # List to store all method outputs
|
||||
self._completed_methods: Set[str] = set() # Track completed methods for reload
|
||||
self._persistence: Optional[FlowPersistence] = persistence
|
||||
|
||||
# Initialize state with initial values
|
||||
@@ -722,73 +718,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
else:
|
||||
raise TypeError(f"State must be dict or BaseModel, got {type(self._state)}")
|
||||
|
||||
def reload(self, execution_data: FlowExecutionData) -> None:
|
||||
"""Reloads the flow from an execution data dict.
|
||||
|
||||
This method restores the flow's execution ID, completed methods, and state,
|
||||
allowing it to resume from where it left off.
|
||||
|
||||
Args:
|
||||
execution_data: Flow execution data containing:
|
||||
- id: Flow execution ID
|
||||
- flow: Flow structure
|
||||
- completed_methods: List of successfully completed methods
|
||||
- execution_methods: All execution methods with their status
|
||||
"""
|
||||
flow_id = execution_data.get("id")
|
||||
if flow_id:
|
||||
self._update_state_field("id", flow_id)
|
||||
|
||||
self._completed_methods = {
|
||||
name
|
||||
for method_data in execution_data.get("completed_methods", [])
|
||||
if (name := method_data.get("flow_method", {}).get("name")) is not None
|
||||
}
|
||||
|
||||
execution_methods = execution_data.get("execution_methods", [])
|
||||
if not execution_methods:
|
||||
return
|
||||
|
||||
sorted_methods = sorted(
|
||||
execution_methods,
|
||||
key=lambda m: m.get("started_at", ""),
|
||||
)
|
||||
|
||||
state_to_apply = None
|
||||
for method in reversed(sorted_methods):
|
||||
if method.get("final_state"):
|
||||
state_to_apply = method["final_state"]
|
||||
break
|
||||
|
||||
if not state_to_apply and sorted_methods:
|
||||
last_method = sorted_methods[-1]
|
||||
if last_method.get("initial_state"):
|
||||
state_to_apply = last_method["initial_state"]
|
||||
|
||||
if state_to_apply:
|
||||
self._apply_state_updates(state_to_apply)
|
||||
|
||||
for i, method in enumerate(sorted_methods[:-1]):
|
||||
method_name = method.get("flow_method", {}).get("name")
|
||||
if method_name:
|
||||
self._completed_methods.add(method_name)
|
||||
|
||||
def _update_state_field(self, field_name: str, value: Any) -> None:
|
||||
"""Update a single field in the state."""
|
||||
if isinstance(self._state, dict):
|
||||
self._state[field_name] = value
|
||||
elif hasattr(self._state, field_name):
|
||||
object.__setattr__(self._state, field_name, value)
|
||||
|
||||
def _apply_state_updates(self, updates: Dict[str, Any]) -> None:
|
||||
"""Apply multiple state updates efficiently."""
|
||||
if isinstance(self._state, dict):
|
||||
self._state.update(updates)
|
||||
elif hasattr(self._state, "__dict__"):
|
||||
for key, value in updates.items():
|
||||
if hasattr(self._state, key):
|
||||
object.__setattr__(self._state, key, value)
|
||||
|
||||
def kickoff(self, inputs: Optional[Dict[str, Any]] = None) -> Any:
|
||||
"""
|
||||
Start the flow execution in a synchronous context.
|
||||
@@ -817,81 +746,68 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
Returns:
|
||||
The final output from the flow, which is the result of the last executed method.
|
||||
"""
|
||||
ctx = baggage.set_baggage("flow_inputs", inputs or {})
|
||||
flow_token = attach(ctx)
|
||||
if inputs:
|
||||
# Override the id in the state if it exists in inputs
|
||||
if "id" in inputs:
|
||||
if isinstance(self._state, dict):
|
||||
self._state["id"] = inputs["id"]
|
||||
elif isinstance(self._state, BaseModel):
|
||||
setattr(self._state, "id", inputs["id"])
|
||||
|
||||
try:
|
||||
# Reset flow state for fresh execution unless restoring from persistence
|
||||
is_restoring = inputs and "id" in inputs and self._persistence is not None
|
||||
if not is_restoring:
|
||||
# Clear completed methods and outputs for a fresh start
|
||||
self._completed_methods.clear()
|
||||
self._method_outputs.clear()
|
||||
# If persistence is enabled, attempt to restore the stored state using the provided id.
|
||||
if "id" in inputs and self._persistence is not None:
|
||||
restore_uuid = inputs["id"]
|
||||
stored_state = self._persistence.load_state(restore_uuid)
|
||||
if stored_state:
|
||||
self._log_flow_event(
|
||||
f"Loading flow state from memory for UUID: {restore_uuid}",
|
||||
color="yellow",
|
||||
)
|
||||
self._restore_state(stored_state)
|
||||
else:
|
||||
self._log_flow_event(
|
||||
f"No flow state found for UUID: {restore_uuid}", color="red"
|
||||
)
|
||||
|
||||
if inputs:
|
||||
# Override the id in the state if it exists in inputs
|
||||
if "id" in inputs:
|
||||
if isinstance(self._state, dict):
|
||||
self._state["id"] = inputs["id"]
|
||||
elif isinstance(self._state, BaseModel):
|
||||
setattr(self._state, "id", inputs["id"])
|
||||
# Update state with any additional inputs (ignoring the 'id' key)
|
||||
filtered_inputs = {k: v for k, v in inputs.items() if k != "id"}
|
||||
if filtered_inputs:
|
||||
self._initialize_state(filtered_inputs)
|
||||
|
||||
# If persistence is enabled, attempt to restore the stored state using the provided id.
|
||||
if "id" in inputs and self._persistence is not None:
|
||||
restore_uuid = inputs["id"]
|
||||
stored_state = self._persistence.load_state(restore_uuid)
|
||||
if stored_state:
|
||||
self._log_flow_event(
|
||||
f"Loading flow state from memory for UUID: {restore_uuid}",
|
||||
color="yellow",
|
||||
)
|
||||
self._restore_state(stored_state)
|
||||
else:
|
||||
self._log_flow_event(
|
||||
f"No flow state found for UUID: {restore_uuid}", color="red"
|
||||
)
|
||||
# Emit FlowStartedEvent and log the start of the flow.
|
||||
crewai_event_bus.emit(
|
||||
self,
|
||||
FlowStartedEvent(
|
||||
type="flow_started",
|
||||
flow_name=self.name or self.__class__.__name__,
|
||||
inputs=inputs,
|
||||
),
|
||||
)
|
||||
self._log_flow_event(
|
||||
f"Flow started with ID: {self.flow_id}", color="bold_magenta"
|
||||
)
|
||||
|
||||
# Update state with any additional inputs (ignoring the 'id' key)
|
||||
filtered_inputs = {k: v for k, v in inputs.items() if k != "id"}
|
||||
if filtered_inputs:
|
||||
self._initialize_state(filtered_inputs)
|
||||
if inputs is not None and "id" not in inputs:
|
||||
self._initialize_state(inputs)
|
||||
|
||||
# Emit FlowStartedEvent and log the start of the flow.
|
||||
crewai_event_bus.emit(
|
||||
self,
|
||||
FlowStartedEvent(
|
||||
type="flow_started",
|
||||
flow_name=self.name or self.__class__.__name__,
|
||||
inputs=inputs,
|
||||
),
|
||||
)
|
||||
self._log_flow_event(
|
||||
f"Flow started with ID: {self.flow_id}", color="bold_magenta"
|
||||
)
|
||||
tasks = [
|
||||
self._execute_start_method(start_method)
|
||||
for start_method in self._start_methods
|
||||
]
|
||||
await asyncio.gather(*tasks)
|
||||
|
||||
if inputs is not None and "id" not in inputs:
|
||||
self._initialize_state(inputs)
|
||||
final_output = self._method_outputs[-1] if self._method_outputs else None
|
||||
|
||||
tasks = [
|
||||
self._execute_start_method(start_method)
|
||||
for start_method in self._start_methods
|
||||
]
|
||||
await asyncio.gather(*tasks)
|
||||
crewai_event_bus.emit(
|
||||
self,
|
||||
FlowFinishedEvent(
|
||||
type="flow_finished",
|
||||
flow_name=self.name or self.__class__.__name__,
|
||||
result=final_output,
|
||||
),
|
||||
)
|
||||
|
||||
final_output = self._method_outputs[-1] if self._method_outputs else None
|
||||
|
||||
crewai_event_bus.emit(
|
||||
self,
|
||||
FlowFinishedEvent(
|
||||
type="flow_finished",
|
||||
flow_name=self.name or self.__class__.__name__,
|
||||
result=final_output,
|
||||
),
|
||||
)
|
||||
|
||||
return final_output
|
||||
finally:
|
||||
detach(flow_token)
|
||||
return final_output
|
||||
|
||||
async def _execute_start_method(self, start_method_name: str) -> None:
|
||||
"""
|
||||
@@ -910,13 +826,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
- Executes the start method and captures its result
|
||||
- Triggers execution of any listeners waiting on this start method
|
||||
- Part of the flow's initialization sequence
|
||||
- Skips execution if method was already completed (e.g., after reload)
|
||||
"""
|
||||
if start_method_name in self._completed_methods:
|
||||
last_output = self._method_outputs[-1] if self._method_outputs else None
|
||||
await self._execute_listeners(start_method_name, last_output)
|
||||
return
|
||||
|
||||
result = await self._execute_method(
|
||||
start_method_name, self._methods[start_method_name]
|
||||
)
|
||||
@@ -951,7 +861,6 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
self._method_execution_counts.get(method_name, 0) + 1
|
||||
)
|
||||
|
||||
self._completed_methods.add(method_name)
|
||||
crewai_event_bus.emit(
|
||||
self,
|
||||
MethodExecutionFinishedEvent(
|
||||
@@ -1114,18 +1023,12 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
- Handles errors gracefully with detailed logging
|
||||
- Recursively triggers listeners of this listener
|
||||
- Supports both parameterized and parameter-less listeners
|
||||
- Skips execution if method was already completed (e.g., after reload)
|
||||
|
||||
Error Handling
|
||||
-------------
|
||||
Catches and logs any exceptions during execution, preventing
|
||||
individual listener failures from breaking the entire flow.
|
||||
"""
|
||||
# TODO: greyson fix
|
||||
# if listener_name in self._completed_methods:
|
||||
# await self._execute_listeners(listener_name, None)
|
||||
# return
|
||||
|
||||
try:
|
||||
method = self._methods[listener_name]
|
||||
|
||||
@@ -1144,7 +1047,12 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
await self._execute_listeners(listener_name, listener_result)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing listener {listener_name}: {e}")
|
||||
print(
|
||||
f"[Flow._execute_single_listener] Error in method {listener_name}: {e}"
|
||||
)
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
def _log_flow_event(
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
"""Type definitions for CrewAI Flow module.
|
||||
|
||||
This module contains TypedDict definitions and type aliases used throughout
|
||||
the Flow system.
|
||||
"""
|
||||
|
||||
from typing import Any, TypedDict
|
||||
from typing_extensions import NotRequired, Required
|
||||
|
||||
|
||||
class FlowMethodData(TypedDict):
|
||||
"""Flow method information.
|
||||
|
||||
Attributes:
|
||||
name: The name of the flow method.
|
||||
starting_point: Whether this method is a starting point for the flow.
|
||||
"""
|
||||
|
||||
name: str
|
||||
starting_point: NotRequired[bool]
|
||||
|
||||
|
||||
class CompletedMethodData(TypedDict):
|
||||
"""Completed method information.
|
||||
|
||||
Represents a flow method that has been successfully executed.
|
||||
|
||||
Attributes:
|
||||
flow_method: The flow method information.
|
||||
status: The completion status of the method.
|
||||
"""
|
||||
|
||||
flow_method: FlowMethodData
|
||||
status: str
|
||||
|
||||
|
||||
class ExecutionMethodData(TypedDict, total=False):
|
||||
"""Execution method information.
|
||||
|
||||
Contains detailed information about a method's execution, including
|
||||
timing, state, and any error details.
|
||||
|
||||
Attributes:
|
||||
flow_method: The flow method information.
|
||||
started_at: ISO timestamp when the method started execution.
|
||||
finished_at: ISO timestamp when the method finished execution, if completed.
|
||||
status: Current status of the method execution.
|
||||
initial_state: The state before method execution.
|
||||
final_state: The state after method execution.
|
||||
error_details: Details about any error that occurred during execution.
|
||||
"""
|
||||
|
||||
flow_method: Required[FlowMethodData]
|
||||
started_at: Required[str]
|
||||
status: Required[str]
|
||||
finished_at: str
|
||||
initial_state: dict[str, Any]
|
||||
final_state: dict[str, Any]
|
||||
error_details: dict[str, Any]
|
||||
|
||||
|
||||
class FlowData(TypedDict):
|
||||
"""Flow structure information.
|
||||
|
||||
Contains metadata about the flow structure and its methods.
|
||||
|
||||
Attributes:
|
||||
name: The name of the flow.
|
||||
flow_methods_attributes: List of all flow methods and their attributes.
|
||||
"""
|
||||
|
||||
name: str
|
||||
flow_methods_attributes: list[FlowMethodData]
|
||||
|
||||
|
||||
class FlowExecutionData(TypedDict):
|
||||
"""Flow execution data.
|
||||
|
||||
Complete execution data for a flow, including its current state,
|
||||
completed methods, and execution history. Used for resuming flows
|
||||
from a previous state.
|
||||
|
||||
Attributes:
|
||||
id: Unique identifier for the flow execution.
|
||||
flow: Flow structure and metadata.
|
||||
inputs: Input data provided to the flow.
|
||||
completed_methods: List of methods that have been successfully completed.
|
||||
execution_methods: Detailed execution history for all methods.
|
||||
"""
|
||||
|
||||
id: str
|
||||
flow: FlowData
|
||||
inputs: dict[str, Any]
|
||||
completed_methods: list[CompletedMethodData]
|
||||
execution_methods: list[ExecutionMethodData]
|
||||
@@ -1,18 +0,0 @@
|
||||
from typing import List, Dict, TypedDict
|
||||
|
||||
|
||||
class HITLResumeInfo(TypedDict, total=False):
|
||||
"""HITL resume information passed from flow to crew."""
|
||||
|
||||
task_id: str
|
||||
crew_execution_id: str
|
||||
task_key: str
|
||||
task_output: str
|
||||
human_feedback: str
|
||||
previous_messages: List[Dict[str, str]]
|
||||
|
||||
|
||||
class CrewInputsWithHITL(TypedDict, total=False):
|
||||
"""Crew inputs that may contain HITL resume information."""
|
||||
|
||||
_hitl_resume: HITLResumeInfo
|
||||
@@ -162,7 +162,7 @@ class EventListener(BaseEventListener):
|
||||
span = self._telemetry.task_started(crew=source.agent.crew, task=source)
|
||||
self.execution_spans[source] = span
|
||||
self.formatter.create_task_branch(
|
||||
self.formatter.current_crew_tree, source.id
|
||||
self.formatter.current_crew_tree, source
|
||||
)
|
||||
|
||||
@crewai_event_bus.on(TaskCompletedEvent)
|
||||
@@ -175,7 +175,7 @@ class EventListener(BaseEventListener):
|
||||
|
||||
self.formatter.update_task_status(
|
||||
self.formatter.current_crew_tree,
|
||||
source.id,
|
||||
source,
|
||||
source.agent.role,
|
||||
"completed",
|
||||
)
|
||||
@@ -190,7 +190,7 @@ class EventListener(BaseEventListener):
|
||||
|
||||
self.formatter.update_task_status(
|
||||
self.formatter.current_crew_tree,
|
||||
source.id,
|
||||
source,
|
||||
source.agent.role,
|
||||
"failed",
|
||||
)
|
||||
|
||||
@@ -220,14 +220,16 @@ class ConsoleFormatter:
|
||||
return tree
|
||||
|
||||
def create_task_branch(
|
||||
self, crew_tree: Optional[Tree], task_id: str
|
||||
self, crew_tree: Optional[Tree], task: Any
|
||||
) -> Optional[Tree]:
|
||||
"""Create and initialize a task branch."""
|
||||
if not self.verbose:
|
||||
return None
|
||||
|
||||
task_display = self._get_task_display_name(task)
|
||||
|
||||
task_content = Text()
|
||||
task_content.append(f"📋 Task: {task_id}", style="yellow bold")
|
||||
task_content.append(f"📋 Task: {task_display}", style="yellow bold")
|
||||
task_content.append("\nStatus: ", style="white")
|
||||
task_content.append("Executing Task...", style="yellow dim")
|
||||
|
||||
@@ -248,7 +250,7 @@ class ConsoleFormatter:
|
||||
def update_task_status(
|
||||
self,
|
||||
crew_tree: Optional[Tree],
|
||||
task_id: str,
|
||||
task: Any,
|
||||
agent_role: str,
|
||||
status: str = "completed",
|
||||
) -> None:
|
||||
@@ -256,6 +258,9 @@ class ConsoleFormatter:
|
||||
if not self.verbose or crew_tree is None:
|
||||
return
|
||||
|
||||
task_display = self._get_task_display_name(task)
|
||||
task_id = str(task.id)
|
||||
|
||||
if status == "completed":
|
||||
style = "green"
|
||||
status_text = "✅ Completed"
|
||||
@@ -267,11 +272,11 @@ class ConsoleFormatter:
|
||||
|
||||
# Update tree label
|
||||
for branch in crew_tree.children:
|
||||
if str(task_id) in str(branch.label):
|
||||
if task_id in str(branch.label):
|
||||
# Build label without introducing stray blank lines
|
||||
task_content = Text()
|
||||
# First line: Task ID
|
||||
task_content.append(f"📋 Task: {task_id}", style=f"{style} bold")
|
||||
# First line: Task name/description
|
||||
task_content.append(f"📋 Task: {task_display}", style=f"{style} bold")
|
||||
|
||||
# Second line: Assigned to
|
||||
task_content.append("\nAssigned to: ", style="white")
|
||||
@@ -286,7 +291,7 @@ class ConsoleFormatter:
|
||||
|
||||
# Show status panel
|
||||
content = self.create_status_content(
|
||||
f"Task {status.title()}", str(task_id), style, Agent=agent_role
|
||||
f"Task {status.title()}", task_display, style, Agent=agent_role
|
||||
)
|
||||
self.print_panel(content, panel_title, style)
|
||||
|
||||
@@ -1754,3 +1759,13 @@ class ConsoleFormatter:
|
||||
Attempts=f"{retry_count + 1}",
|
||||
)
|
||||
self.print_panel(content, "🛡️ Guardrail Failed", "red")
|
||||
|
||||
def _get_task_display_name(self, task: Any) -> str:
|
||||
"""Get display name for a task, with fallback logic."""
|
||||
if hasattr(task, 'name') and task.name:
|
||||
return f"{task.name} (ID: {str(task.id)[:8]}...)"
|
||||
elif hasattr(task, 'description') and task.description:
|
||||
desc = task.description[:50] + "..." if len(task.description) > 50 else task.description
|
||||
return f"{desc} (ID: {str(task.id)[:8]}...)"
|
||||
else:
|
||||
return str(task.id)
|
||||
|
||||
44
test_verbose_fix.py
Normal file
44
test_verbose_fix.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script to verify verbose output shows task names instead of IDs."""
|
||||
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
def test_verbose_output():
|
||||
"""Test that verbose output shows task names instead of UUIDs."""
|
||||
print("Testing verbose output with task names...")
|
||||
|
||||
agent = Agent(
|
||||
role="Research Analyst",
|
||||
goal="Analyze data and provide insights",
|
||||
backstory="You are an experienced data analyst.",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
task = Task(
|
||||
name="Market Research Analysis",
|
||||
description="Research current market trends in AI technology",
|
||||
expected_output="A comprehensive report on AI market trends",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
print("Task name:", task.name)
|
||||
print("Task ID:", task.id)
|
||||
print("\nRunning crew with verbose=True...")
|
||||
print("Expected: Should show task name 'Market Research Analysis' instead of UUID")
|
||||
|
||||
try:
|
||||
crew.kickoff()
|
||||
print("\nCrew execution completed successfully!")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error during execution: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_verbose_output()
|
||||
95
tests/utilities/test_console_formatter_verbose.py
Normal file
95
tests/utilities/test_console_formatter_verbose.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from unittest.mock import Mock, patch
|
||||
from crewai.utilities.events.utils.console_formatter import ConsoleFormatter
|
||||
|
||||
|
||||
class TestConsoleFormatterVerbose:
|
||||
"""Test verbose output functionality in console formatter."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Set up test fixtures."""
|
||||
self.formatter = ConsoleFormatter(verbose=True)
|
||||
|
||||
def test_get_task_display_name_with_name(self):
|
||||
"""Test task display name when task has a name."""
|
||||
task = Mock()
|
||||
task.name = "Research Market Trends"
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
result = self.formatter._get_task_display_name(task)
|
||||
assert "Research Market Trends" in result
|
||||
assert "12345678" in result
|
||||
|
||||
def test_get_task_display_name_with_description_only(self):
|
||||
"""Test task display name when task has no name but has description."""
|
||||
task = Mock()
|
||||
task.name = None
|
||||
task.description = "Analyze current market trends and provide insights"
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
result = self.formatter._get_task_display_name(task)
|
||||
assert "Analyze current market trends" in result
|
||||
assert "12345678" in result
|
||||
|
||||
def test_get_task_display_name_long_description_truncated(self):
|
||||
"""Test task display name truncates long descriptions."""
|
||||
task = Mock()
|
||||
task.name = None
|
||||
task.description = "This is a very long task description that should be truncated because it exceeds the maximum length"
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
result = self.formatter._get_task_display_name(task)
|
||||
assert len(result.split("(ID:")[0].strip()) <= 53
|
||||
assert "..." in result
|
||||
|
||||
def test_get_task_display_name_fallback_to_id(self):
|
||||
"""Test task display name falls back to ID when no name or description."""
|
||||
task = Mock()
|
||||
task.name = None
|
||||
task.description = None
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
result = self.formatter._get_task_display_name(task)
|
||||
assert result == "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
@patch('crewai.utilities.events.utils.console_formatter.ConsoleFormatter.print')
|
||||
def test_create_task_branch_uses_task_name(self, mock_print):
|
||||
"""Test create_task_branch displays task name instead of ID."""
|
||||
task = Mock()
|
||||
task.name = "Write Blog Post"
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
crew_tree = Mock()
|
||||
crew_tree.add.return_value = Mock()
|
||||
|
||||
self.formatter.create_task_branch(crew_tree, task)
|
||||
|
||||
call_args = crew_tree.add.call_args[0][0]
|
||||
assert "Write Blog Post" in str(call_args)
|
||||
assert "12345678" in str(call_args)
|
||||
|
||||
@patch('crewai.utilities.events.utils.console_formatter.ConsoleFormatter.print')
|
||||
def test_update_task_status_uses_task_name(self, mock_print):
|
||||
"""Test update_task_status displays task name instead of ID."""
|
||||
task = Mock()
|
||||
task.name = "Data Analysis"
|
||||
task.id = "12345678-1234-5678-9012-123456789abc"
|
||||
|
||||
crew_tree = Mock()
|
||||
branch = Mock()
|
||||
branch.label = "12345678-1234-5678-9012-123456789abc"
|
||||
crew_tree.children = [branch]
|
||||
|
||||
self.formatter.update_task_status(crew_tree, task, "Data Analyst", "completed")
|
||||
|
||||
updated_label = branch.label
|
||||
assert "Data Analysis" in str(updated_label)
|
||||
|
||||
def test_verbose_disabled_returns_none(self):
|
||||
"""Test that methods return None when verbose is disabled."""
|
||||
formatter = ConsoleFormatter(verbose=False)
|
||||
task = Mock()
|
||||
|
||||
result = formatter.create_task_branch(Mock(), task)
|
||||
assert result is None
|
||||
|
||||
formatter.update_task_status(Mock(), task, "Agent", "completed")
|
||||
8
uv.lock
generated
8
uv.lock
generated
@@ -798,7 +798,7 @@ requires-dist = [
|
||||
{ name = "blinker", specifier = ">=1.9.0" },
|
||||
{ name = "chromadb", specifier = ">=0.5.23" },
|
||||
{ name = "click", specifier = ">=8.1.7" },
|
||||
{ name = "crewai-tools", marker = "extra == 'tools'", specifier = "~=0.62.0" },
|
||||
{ name = "crewai-tools", marker = "extra == 'tools'", specifier = "~=0.60.0" },
|
||||
{ name = "docling", marker = "extra == 'docling'", specifier = ">=2.12.0" },
|
||||
{ name = "instructor", specifier = ">=1.3.3" },
|
||||
{ name = "json-repair", specifier = "==0.25.2" },
|
||||
@@ -850,7 +850,7 @@ dev = [
|
||||
|
||||
[[package]]
|
||||
name = "crewai-tools"
|
||||
version = "0.62.0"
|
||||
version = "0.60.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "chromadb" },
|
||||
@@ -868,9 +868,9 @@ dependencies = [
|
||||
{ name = "stagehand" },
|
||||
{ name = "tiktoken" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e9/24/0287edbaa33c52b5541a564d92d3324d4839a76a4b023540c0fd5c7ee330/crewai_tools-0.62.0.tar.gz", hash = "sha256:71a24c173677f108516e1cde286e476e9aeb60da78d911bec0f15caa3c6af15a", size = 1059534, upload-time = "2025-08-13T21:13:49.879Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bb/60/04fd70a8a15eaf4147ff648ada44f1d4afd453a528cf8facd618ef32e576/crewai_tools-0.60.0.tar.gz", hash = "sha256:9234f6912b65495afe5e1bfa330abca09a40725d47fe2c71a22387bf6eeb8e72", size = 1032373, upload-time = "2025-08-06T20:27:16.003Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/16/cf26f4eaf1edc2f62d0c9cb1ec97f573f8d7401663da047c52b3ce4c4628/crewai_tools-0.62.0-py3-none-any.whl", hash = "sha256:b5e7035563cb00601431286b1c56933966acea1f220052cd33e1d4ee35590017", size = 677008, upload-time = "2025-08-13T21:13:46.903Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/55/984f3d2d5afbcfa87c380c7c17b728804e80617b768b3748f25220b2b32c/crewai_tools-0.60.0-py3-none-any.whl", hash = "sha256:a54277c973753de4a3269da17e5a7e4995d4c70fc331eb2872189b5f92cfdaaf", size = 657128, upload-time = "2025-08-06T20:27:14.295Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in New Issue
Block a user