Compare commits
84 Commits
devin/1768
...
codex/nl2s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb0a8c4549 | ||
|
|
6c0fb7f970 | ||
|
|
db0c8ff468 | ||
|
|
cde33fd981 | ||
|
|
1f8cfe3282 | ||
|
|
2ed0c2c043 | ||
|
|
0341e5aee7 | ||
|
|
397d14c772 | ||
|
|
fc3e86e9a3 | ||
|
|
2882df5daf | ||
|
|
3a22e80764 | ||
|
|
9b585a934d | ||
|
|
46e1b02154 | ||
|
|
87675b49fd | ||
|
|
a3bee66be8 | ||
|
|
f6fa04528a | ||
|
|
7d498b29be | ||
|
|
1308bdee63 | ||
|
|
6bb1b178a1 | ||
|
|
fe2a4b4e40 | ||
|
|
711e7171e1 | ||
|
|
76b5f72e81 | ||
|
|
d86d43d3e0 | ||
|
|
6bfc98e960 | ||
|
|
3cc33ef6ab | ||
|
|
3fec4669af | ||
|
|
d3f424fd8f | ||
|
|
fee9445067 | ||
|
|
a3c01265ee | ||
|
|
aa7e7785bc | ||
|
|
e30645e855 | ||
|
|
c1d2801be2 | ||
|
|
6a8483fcb6 | ||
|
|
5fb602dff2 | ||
|
|
b90cff580a | ||
|
|
576b74b2ef | ||
|
|
7590d4c6e3 | ||
|
|
8c6436234b | ||
|
|
96bde4510b | ||
|
|
9d7f45376a | ||
|
|
536447ab0e | ||
|
|
63a508f601 | ||
|
|
102b6ae855 | ||
|
|
19ce56032c | ||
|
|
85f31459c1 | ||
|
|
6fcf748dae | ||
|
|
38065e29ce | ||
|
|
e291a97bdd | ||
|
|
2d05e59223 | ||
|
|
a731efac8d | ||
|
|
1e27cf3f0f | ||
|
|
381ad3a9a8 | ||
|
|
f53bdb28ac | ||
|
|
3b17026082 | ||
|
|
d52dbc1f4b | ||
|
|
6b926b90d0 | ||
|
|
fc84daadbb | ||
|
|
58b866a83d | ||
|
|
9797567342 | ||
|
|
a32de6bdac | ||
|
|
06a58e463c | ||
|
|
3d771f03fa | ||
|
|
db7aeb5a00 | ||
|
|
0cb40374de | ||
|
|
0f3208197f | ||
|
|
c4c9208229 | ||
|
|
bd4d039f63 | ||
|
|
06d953bf46 | ||
|
|
f997b73577 | ||
|
|
7a65baeb9c | ||
|
|
741bf12bf4 | ||
|
|
b267bb4054 | ||
|
|
ceef062426 | ||
|
|
e44d778e0e | ||
|
|
5645cbb22e | ||
|
|
8f022be106 | ||
|
|
6a19b0a279 | ||
|
|
641c336b2c | ||
|
|
22f1812824 | ||
|
|
9edbf89b68 | ||
|
|
685f7b9af1 | ||
|
|
595fdfb6e7 | ||
|
|
8f99fa76ed | ||
|
|
17e3fcbe1f |
1429
.cursorrules
5
.github/codeql/codeql-config.yml
vendored
@@ -14,13 +14,18 @@ paths-ignore:
|
||||
- "lib/crewai/src/crewai/experimental/a2a/**"
|
||||
|
||||
paths:
|
||||
# Include GitHub Actions workflows/composite actions for CodeQL actions analysis
|
||||
- ".github/workflows/**"
|
||||
- ".github/actions/**"
|
||||
# Include all Python source code from workspace packages
|
||||
- "lib/crewai/src/**"
|
||||
- "lib/crewai-tools/src/**"
|
||||
- "lib/crewai-files/src/**"
|
||||
- "lib/devtools/src/**"
|
||||
# Include tests (but exclude cassettes via paths-ignore)
|
||||
- "lib/crewai/tests/**"
|
||||
- "lib/crewai-tools/tests/**"
|
||||
- "lib/crewai-files/tests/**"
|
||||
- "lib/devtools/tests/**"
|
||||
|
||||
# Configure specific queries or packs if needed
|
||||
|
||||
9
.github/dependabot.yml
vendored
@@ -5,7 +5,12 @@
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: uv # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
- package-ecosystem: uv
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
security-updates:
|
||||
applies-to: security-updates
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
4
.github/workflows/codeql.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
@@ -98,6 +98,6 @@ jobs:
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
63
.github/workflows/generate-tool-specs.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Generate Tool Specifications
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'lib/crewai-tools/src/crewai_tools/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
generate-specs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
id: app-token
|
||||
uses: tibdex/github-app-token@v2
|
||||
with:
|
||||
app_id: ${{ secrets.CREWAI_TOOL_SPECS_APP_ID }}
|
||||
private_key: ${{ secrets.CREWAI_TOOL_SPECS_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
version: "0.8.4"
|
||||
python-version: "3.12"
|
||||
enable-cache: true
|
||||
|
||||
- name: Install the project
|
||||
working-directory: lib/crewai-tools
|
||||
run: uv sync --dev --all-extras
|
||||
|
||||
- name: Generate tool specifications
|
||||
working-directory: lib/crewai-tools
|
||||
run: uv run python src/crewai_tools/generate_tool_specs.py
|
||||
|
||||
- name: Check for changes and commit
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git add lib/crewai-tools/tool.specs.json
|
||||
|
||||
if git diff --quiet --staged; then
|
||||
echo "No changes detected in tool.specs.json"
|
||||
else
|
||||
echo "Changes detected in tool.specs.json, committing..."
|
||||
git commit -m "chore: update tool specifications"
|
||||
git push
|
||||
fi
|
||||
1
.gitignore
vendored
@@ -26,3 +26,4 @@ plan.md
|
||||
conceptual_plan.md
|
||||
build_image
|
||||
chromadb-*.lock
|
||||
.claude
|
||||
|
||||
@@ -19,7 +19,7 @@ repos:
|
||||
language: system
|
||||
pass_filenames: true
|
||||
types: [python]
|
||||
exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/crewai/tests/|lib/crewai-tools/tests/)
|
||||
exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/crewai/tests/|lib/crewai-tools/tests/|lib/crewai-files/tests/)
|
||||
- repo: https://github.com/astral-sh/uv-pre-commit
|
||||
rev: 0.9.3
|
||||
hooks:
|
||||
|
||||
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
||||
77
conftest.py
@@ -1,6 +1,8 @@
|
||||
"""Pytest configuration for crewAI workspace."""
|
||||
|
||||
import base64
|
||||
from collections.abc import Generator
|
||||
import gzip
|
||||
import os
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
@@ -9,6 +11,7 @@ from typing import Any
|
||||
from dotenv import load_dotenv
|
||||
import pytest
|
||||
from vcr.request import Request # type: ignore[import-untyped]
|
||||
import vcr.stubs.httpx_stubs as httpx_stubs # type: ignore[import-untyped]
|
||||
|
||||
|
||||
env_test_path = Path(__file__).parent / ".env.test"
|
||||
@@ -16,6 +19,25 @@ load_dotenv(env_test_path, override=True)
|
||||
load_dotenv(override=True)
|
||||
|
||||
|
||||
def _patched_make_vcr_request(httpx_request: Any, **kwargs: Any) -> Any:
|
||||
"""Patched version of VCR's _make_vcr_request that handles binary content.
|
||||
|
||||
The original implementation fails on binary request bodies (like file uploads)
|
||||
because it assumes all content can be decoded as UTF-8.
|
||||
"""
|
||||
raw_body = httpx_request.read()
|
||||
try:
|
||||
body = raw_body.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
body = base64.b64encode(raw_body).decode("ascii")
|
||||
uri = str(httpx_request.url)
|
||||
headers = dict(httpx_request.headers)
|
||||
return Request(httpx_request.method, uri, body, headers)
|
||||
|
||||
|
||||
httpx_stubs._make_vcr_request = _patched_make_vcr_request
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="function")
|
||||
def cleanup_event_handlers() -> Generator[None, Any, None]:
|
||||
"""Clean up event bus handlers after each test to prevent test pollution."""
|
||||
@@ -31,6 +53,21 @@ def cleanup_event_handlers() -> Generator[None, Any, None]:
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="function")
|
||||
def reset_event_state() -> None:
|
||||
"""Reset event system state before each test for isolation."""
|
||||
from crewai.events.base_events import reset_emission_counter
|
||||
from crewai.events.event_context import (
|
||||
EventContextConfig,
|
||||
_event_context_config,
|
||||
_event_id_stack,
|
||||
)
|
||||
|
||||
reset_emission_counter()
|
||||
_event_id_stack.set(())
|
||||
_event_context_config.set(EventContextConfig())
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="function")
|
||||
def setup_test_environment() -> Generator[None, Any, None]:
|
||||
"""Setup test environment for crewAI workspace."""
|
||||
@@ -133,19 +170,42 @@ def _filter_request_headers(request: Request) -> Request: # type: ignore[no-any
|
||||
request.headers[variant] = [replacement]
|
||||
|
||||
request.method = request.method.upper()
|
||||
|
||||
# Normalize Azure OpenAI endpoints to a consistent placeholder for cassette matching.
|
||||
if request.host and request.host.endswith(".openai.azure.com"):
|
||||
original_host = request.host
|
||||
placeholder_host = "fake-azure-endpoint.openai.azure.com"
|
||||
request.uri = request.uri.replace(original_host, placeholder_host)
|
||||
|
||||
return request
|
||||
|
||||
|
||||
def _filter_response_headers(response: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Filter sensitive headers from response before recording."""
|
||||
# Remove Content-Encoding to prevent decompression issues on replay
|
||||
def _filter_response_headers(response: dict[str, Any]) -> dict[str, Any] | None:
|
||||
"""Filter sensitive headers from response before recording.
|
||||
|
||||
Returns None to skip recording responses with empty bodies. This handles
|
||||
duplicate recordings caused by OpenAI's stainless client using
|
||||
with_raw_response which triggers httpx to re-read the consumed stream.
|
||||
"""
|
||||
body = response.get("body", {}).get("string", "")
|
||||
headers = response.get("headers", {})
|
||||
content_length = headers.get("content-length", headers.get("Content-Length", []))
|
||||
|
||||
if body == "" or body == b"" or content_length == ["0"]:
|
||||
return None
|
||||
|
||||
for encoding_header in ["Content-Encoding", "content-encoding"]:
|
||||
response["headers"].pop(encoding_header, None)
|
||||
if encoding_header in headers:
|
||||
encoding = headers.pop(encoding_header)
|
||||
if encoding and encoding[0] == "gzip":
|
||||
body = response.get("body", {}).get("string", b"")
|
||||
if isinstance(body, bytes) and body.startswith(b"\x1f\x8b"):
|
||||
response["body"]["string"] = gzip.decompress(body).decode("utf-8")
|
||||
|
||||
for header_name, replacement in HEADERS_TO_FILTER.items():
|
||||
for variant in [header_name, header_name.upper(), header_name.title()]:
|
||||
if variant in response["headers"]:
|
||||
response["headers"][variant] = [replacement]
|
||||
if variant in headers:
|
||||
headers[variant] = [replacement]
|
||||
return response
|
||||
|
||||
|
||||
@@ -160,7 +220,10 @@ def vcr_cassette_dir(request: Any) -> str:
|
||||
test_file = Path(request.fspath)
|
||||
|
||||
for parent in test_file.parents:
|
||||
if parent.name in ("crewai", "crewai-tools") and parent.parent.name == "lib":
|
||||
if (
|
||||
parent.name in ("crewai", "crewai-tools", "crewai-files")
|
||||
and parent.parent.name == "lib"
|
||||
):
|
||||
package_root = parent
|
||||
break
|
||||
else:
|
||||
|
||||
@@ -111,6 +111,13 @@
|
||||
"en/guides/flows/mastering-flow-state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Coding Tools",
|
||||
"icon": "terminal",
|
||||
"pages": [
|
||||
"en/guides/coding-tools/agents-md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Advanced",
|
||||
"icon": "gear",
|
||||
@@ -131,6 +138,7 @@
|
||||
"en/concepts/production-architecture",
|
||||
"en/concepts/knowledge",
|
||||
"en/concepts/llms",
|
||||
"en/concepts/files",
|
||||
"en/concepts/processes",
|
||||
"en/concepts/collaboration",
|
||||
"en/concepts/training",
|
||||
@@ -291,6 +299,7 @@
|
||||
"en/observability/arize-phoenix",
|
||||
"en/observability/braintrust",
|
||||
"en/observability/datadog",
|
||||
"en/observability/galileo",
|
||||
"en/observability/langdb",
|
||||
"en/observability/langfuse",
|
||||
"en/observability/langtrace",
|
||||
@@ -368,7 +377,8 @@
|
||||
"pages": [
|
||||
"en/enterprise/features/traces",
|
||||
"en/enterprise/features/webhook-streaming",
|
||||
"en/enterprise/features/hallucination-guardrail"
|
||||
"en/enterprise/features/hallucination-guardrail",
|
||||
"en/enterprise/features/flow-hitl-management"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -428,7 +438,8 @@
|
||||
"group": "How-To Guides",
|
||||
"pages": [
|
||||
"en/enterprise/guides/build-crew",
|
||||
"en/enterprise/guides/deploy-crew",
|
||||
"en/enterprise/guides/prepare-for-deployment",
|
||||
"en/enterprise/guides/deploy-to-amp",
|
||||
"en/enterprise/guides/kickoff-crew",
|
||||
"en/enterprise/guides/update-crew",
|
||||
"en/enterprise/guides/enable-crew-studio",
|
||||
@@ -595,6 +606,7 @@
|
||||
"pt-BR/concepts/production-architecture",
|
||||
"pt-BR/concepts/knowledge",
|
||||
"pt-BR/concepts/llms",
|
||||
"pt-BR/concepts/files",
|
||||
"pt-BR/concepts/processes",
|
||||
"pt-BR/concepts/collaboration",
|
||||
"pt-BR/concepts/training",
|
||||
@@ -742,6 +754,7 @@
|
||||
"pt-BR/observability/arize-phoenix",
|
||||
"pt-BR/observability/braintrust",
|
||||
"pt-BR/observability/datadog",
|
||||
"pt-BR/observability/galileo",
|
||||
"pt-BR/observability/langdb",
|
||||
"pt-BR/observability/langfuse",
|
||||
"pt-BR/observability/langtrace",
|
||||
@@ -818,7 +831,8 @@
|
||||
"pages": [
|
||||
"pt-BR/enterprise/features/traces",
|
||||
"pt-BR/enterprise/features/webhook-streaming",
|
||||
"pt-BR/enterprise/features/hallucination-guardrail"
|
||||
"pt-BR/enterprise/features/hallucination-guardrail",
|
||||
"pt-BR/enterprise/features/flow-hitl-management"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -862,7 +876,8 @@
|
||||
"group": "Guias",
|
||||
"pages": [
|
||||
"pt-BR/enterprise/guides/build-crew",
|
||||
"pt-BR/enterprise/guides/deploy-crew",
|
||||
"pt-BR/enterprise/guides/prepare-for-deployment",
|
||||
"pt-BR/enterprise/guides/deploy-to-amp",
|
||||
"pt-BR/enterprise/guides/kickoff-crew",
|
||||
"pt-BR/enterprise/guides/update-crew",
|
||||
"pt-BR/enterprise/guides/enable-crew-studio",
|
||||
@@ -1044,6 +1059,7 @@
|
||||
"ko/concepts/production-architecture",
|
||||
"ko/concepts/knowledge",
|
||||
"ko/concepts/llms",
|
||||
"ko/concepts/files",
|
||||
"ko/concepts/processes",
|
||||
"ko/concepts/collaboration",
|
||||
"ko/concepts/training",
|
||||
@@ -1203,6 +1219,7 @@
|
||||
"ko/observability/arize-phoenix",
|
||||
"ko/observability/braintrust",
|
||||
"ko/observability/datadog",
|
||||
"ko/observability/galileo",
|
||||
"ko/observability/langdb",
|
||||
"ko/observability/langfuse",
|
||||
"ko/observability/langtrace",
|
||||
@@ -1279,7 +1296,8 @@
|
||||
"pages": [
|
||||
"ko/enterprise/features/traces",
|
||||
"ko/enterprise/features/webhook-streaming",
|
||||
"ko/enterprise/features/hallucination-guardrail"
|
||||
"ko/enterprise/features/hallucination-guardrail",
|
||||
"ko/enterprise/features/flow-hitl-management"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1323,7 +1341,8 @@
|
||||
"group": "How-To Guides",
|
||||
"pages": [
|
||||
"ko/enterprise/guides/build-crew",
|
||||
"ko/enterprise/guides/deploy-crew",
|
||||
"ko/enterprise/guides/prepare-for-deployment",
|
||||
"ko/enterprise/guides/deploy-to-amp",
|
||||
"ko/enterprise/guides/kickoff-crew",
|
||||
"ko/enterprise/guides/update-crew",
|
||||
"ko/enterprise/guides/enable-crew-studio",
|
||||
@@ -1511,6 +1530,18 @@
|
||||
"source": "/enterprise/:path*",
|
||||
"destination": "/en/enterprise/:path*"
|
||||
},
|
||||
{
|
||||
"source": "/en/enterprise/guides/deploy-crew",
|
||||
"destination": "/en/enterprise/guides/deploy-to-amp"
|
||||
},
|
||||
{
|
||||
"source": "/ko/enterprise/guides/deploy-crew",
|
||||
"destination": "/ko/enterprise/guides/deploy-to-amp"
|
||||
},
|
||||
{
|
||||
"source": "/pt-BR/enterprise/guides/deploy-crew",
|
||||
"destination": "/pt-BR/enterprise/guides/deploy-to-amp"
|
||||
},
|
||||
{
|
||||
"source": "/api-reference/:path*",
|
||||
"destination": "/en/api-reference/:path*"
|
||||
@@ -1547,4 +1578,4 @@
|
||||
"reddit": "https://www.reddit.com/r/crewAIInc/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,74 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="Jan 26, 2026">
|
||||
## v1.9.0
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.9.0)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add structured outputs and response_format support across providers
|
||||
- Add response ID to streaming responses
|
||||
- Add event ordering with parent-child hierarchies
|
||||
- Add Keycloak SSO authentication support
|
||||
- Add multimodal file handling capabilities
|
||||
- Add native OpenAI responses API support
|
||||
- Add A2A task execution utilities
|
||||
- Add A2A server configuration and agent card generation
|
||||
- Enhance event system and expand transport options
|
||||
- Improve tool calling mechanisms
|
||||
|
||||
### Bug Fixes
|
||||
- Enhance file store with fallback memory cache when aiocache is not available
|
||||
- Ensure document list is not empty
|
||||
- Handle Bedrock stop sequences properly
|
||||
- Add Google Vertex API key support
|
||||
- Enhance Azure model stop word detection
|
||||
- Improve error handling for HumanFeedbackPending in flow execution
|
||||
- Fix execution span task unlinking
|
||||
|
||||
### Documentation
|
||||
- Add native file handling documentation
|
||||
- Add OpenAI responses API documentation
|
||||
- Add agent card implementation guidance
|
||||
- Refine A2A documentation
|
||||
- Update changelog for v1.8.0
|
||||
|
||||
### Contributors
|
||||
@Anaisdg, @GininDenis, @Vidit-Ostwal, @greysonlalonde, @heitorado, @joaomdmoura, @koushiv777, @lorenzejay, @nicoferdi96, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Jan 15, 2026">
|
||||
## v1.8.1
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.8.1)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add A2A task execution utilities
|
||||
- Add A2A server configuration and agent card generation
|
||||
- Add additional transport mechanisms
|
||||
- Add Galileo integration support
|
||||
|
||||
### Bug Fixes
|
||||
- Improve Azure model compatibility
|
||||
- Expand frame inspection depth to detect parent_flow
|
||||
- Resolve task execution span management issues
|
||||
- Enhance error handling for human feedback scenarios during flow execution
|
||||
|
||||
### Documentation
|
||||
- Add A2A agent card documentation
|
||||
- Add PII redaction feature documentation
|
||||
|
||||
### Contributors
|
||||
@Anaisdg, @GininDenis, @greysonlalonde, @joaomdmoura, @koushiv777, @lorenzejay, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Jan 08, 2026">
|
||||
## v1.8.0
|
||||
|
||||
|
||||
267
docs/en/concepts/files.mdx
Normal file
@@ -0,0 +1,267 @@
|
||||
---
|
||||
title: Files
|
||||
description: Pass images, PDFs, audio, video, and text files to your agents for multimodal processing.
|
||||
icon: file-image
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
CrewAI supports native multimodal file inputs, allowing you to pass images, PDFs, audio, video, and text files directly to your agents. Files are automatically formatted for each LLM provider's API requirements.
|
||||
|
||||
<Note type="info" title="Optional Dependency">
|
||||
File support requires the optional `crewai-files` package. Install it with:
|
||||
|
||||
```bash
|
||||
uv add 'crewai[file-processing]'
|
||||
```
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="Early Access">
|
||||
The file processing API is currently in early access.
|
||||
</Note>
|
||||
|
||||
## File Types
|
||||
|
||||
CrewAI supports five specific file types plus a generic `File` class that auto-detects the type:
|
||||
|
||||
| Type | Class | Use Cases |
|
||||
|:-----|:------|:----------|
|
||||
| **Image** | `ImageFile` | Photos, screenshots, diagrams, charts |
|
||||
| **PDF** | `PDFFile` | Documents, reports, papers |
|
||||
| **Audio** | `AudioFile` | Voice recordings, podcasts, meetings |
|
||||
| **Video** | `VideoFile` | Screen recordings, presentations |
|
||||
| **Text** | `TextFile` | Code files, logs, data files |
|
||||
| **Generic** | `File` | Auto-detect type from content |
|
||||
|
||||
```python
|
||||
from crewai_files import File, ImageFile, PDFFile, AudioFile, VideoFile, TextFile
|
||||
|
||||
image = ImageFile(source="screenshot.png")
|
||||
pdf = PDFFile(source="report.pdf")
|
||||
audio = AudioFile(source="meeting.mp3")
|
||||
video = VideoFile(source="demo.mp4")
|
||||
text = TextFile(source="data.csv")
|
||||
|
||||
file = File(source="document.pdf")
|
||||
```
|
||||
|
||||
## File Sources
|
||||
|
||||
The `source` parameter accepts multiple input types and auto-detects the appropriate handler:
|
||||
|
||||
### From Path
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="./images/chart.png")
|
||||
```
|
||||
|
||||
### From URL
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="https://example.com/image.png")
|
||||
```
|
||||
|
||||
### From Bytes
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, FileBytes
|
||||
|
||||
image_bytes = download_image_from_api()
|
||||
image = ImageFile(source=FileBytes(data=image_bytes, filename="downloaded.png"))
|
||||
image = ImageFile(source=image_bytes)
|
||||
```
|
||||
|
||||
## Using Files
|
||||
|
||||
Files can be passed at multiple levels, with more specific levels taking precedence.
|
||||
|
||||
### With Crews
|
||||
|
||||
Pass files when kicking off a crew:
|
||||
|
||||
```python
|
||||
from crewai import Crew
|
||||
from crewai_files import ImageFile
|
||||
|
||||
crew = Crew(agents=[analyst], tasks=[analysis_task])
|
||||
|
||||
result = crew.kickoff(
|
||||
inputs={"topic": "Q4 Sales"},
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
"report": PDFFile(source="quarterly_report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### With Tasks
|
||||
|
||||
Attach files to specific tasks:
|
||||
|
||||
```python
|
||||
from crewai import Task
|
||||
from crewai_files import ImageFile
|
||||
|
||||
task = Task(
|
||||
description="Analyze the sales chart and identify trends in {chart}",
|
||||
expected_output="A summary of key trends",
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### With Flows
|
||||
|
||||
Pass files to flows, which automatically inherit to crews:
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai_files import ImageFile
|
||||
|
||||
class AnalysisFlow(Flow):
|
||||
@start()
|
||||
def analyze(self):
|
||||
return self.analysis_crew.kickoff()
|
||||
|
||||
flow = AnalysisFlow()
|
||||
result = flow.kickoff(
|
||||
input_files={"image": ImageFile(source="data.png")}
|
||||
)
|
||||
```
|
||||
|
||||
### With Standalone Agents
|
||||
|
||||
Pass files directly to agent kickoff:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai_files import ImageFile
|
||||
|
||||
agent = Agent(
|
||||
role="Image Analyst",
|
||||
goal="Analyze images",
|
||||
backstory="Expert at visual analysis",
|
||||
llm="gpt-4o",
|
||||
)
|
||||
|
||||
result = agent.kickoff(
|
||||
messages="What's in this image?",
|
||||
input_files={"photo": ImageFile(source="photo.jpg")},
|
||||
)
|
||||
```
|
||||
|
||||
## File Precedence
|
||||
|
||||
When files are passed at multiple levels, more specific levels override broader ones:
|
||||
|
||||
```
|
||||
Flow input_files < Crew input_files < Task input_files
|
||||
```
|
||||
|
||||
For example, if both Flow and Task define a file named `"chart"`, the Task's version is used.
|
||||
|
||||
## Provider Support
|
||||
|
||||
Different providers support different file types. CrewAI automatically formats files for each provider's API.
|
||||
|
||||
| Provider | Image | PDF | Audio | Video | Text |
|
||||
|:---------|:-----:|:---:|:-----:|:-----:|:----:|
|
||||
| **OpenAI** (completions API) | ✓ | | | | |
|
||||
| **OpenAI** (responses API) | ✓ | ✓ | ✓ | | |
|
||||
| **Anthropic** (claude-3.x) | ✓ | ✓ | | | |
|
||||
| **Google Gemini** (gemini-1.5, 2.0, 2.5) | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| **AWS Bedrock** (claude-3) | ✓ | ✓ | | | |
|
||||
| **Azure OpenAI** (gpt-4o) | ✓ | | ✓ | | |
|
||||
|
||||
<Note type="info" title="Gemini for Maximum File Support">
|
||||
Google Gemini models support all file types including video (up to 1 hour, 2GB). Use Gemini when you need to process video content.
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="Unsupported File Types">
|
||||
If you pass a file type that the provider doesn't support (e.g., video to OpenAI), you'll receive an `UnsupportedFileTypeError`. Choose your provider based on the file types you need to process.
|
||||
</Note>
|
||||
|
||||
## How Files Are Sent
|
||||
|
||||
CrewAI automatically chooses the optimal method to send files to each provider:
|
||||
|
||||
| Method | Description | Used When |
|
||||
|:-------|:------------|:----------|
|
||||
| **Inline Base64** | File embedded directly in the request | Small files (< 5MB typically) |
|
||||
| **File Upload API** | File uploaded separately, referenced by ID | Large files that exceed threshold |
|
||||
| **URL Reference** | Direct URL passed to the model | File source is already a URL |
|
||||
|
||||
### Provider Transmission Methods
|
||||
|
||||
| Provider | Inline Base64 | File Upload API | URL References |
|
||||
|:---------|:-------------:|:---------------:|:--------------:|
|
||||
| **OpenAI** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Anthropic** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Google Gemini** | ✓ | ✓ (> 20 MB) | ✓ |
|
||||
| **AWS Bedrock** | ✓ | | ✓ (S3 URIs) |
|
||||
| **Azure OpenAI** | ✓ | | ✓ |
|
||||
|
||||
<Note type="info" title="Automatic Optimization">
|
||||
You don't need to manage this yourself. CrewAI automatically uses the most efficient method based on file size and provider capabilities. Providers without file upload APIs use inline base64 for all files.
|
||||
</Note>
|
||||
|
||||
## File Handling Modes
|
||||
|
||||
Control how files are processed when they exceed provider limits:
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
image = ImageFile(source="large.png", mode="strict")
|
||||
image = ImageFile(source="large.png", mode="auto")
|
||||
image = ImageFile(source="large.png", mode="warn")
|
||||
pdf = PDFFile(source="large.pdf", mode="chunk")
|
||||
```
|
||||
|
||||
## Provider Constraints
|
||||
|
||||
Each provider has specific limits for file sizes and dimensions:
|
||||
|
||||
### OpenAI
|
||||
- **Images**: Max 20 MB, up to 10 images per request
|
||||
- **PDFs**: Max 32 MB, up to 100 pages
|
||||
- **Audio**: Max 25 MB, up to 25 minutes
|
||||
|
||||
### Anthropic
|
||||
- **Images**: Max 5 MB, max 8000x8000 pixels, up to 100 images
|
||||
- **PDFs**: Max 32 MB, up to 100 pages
|
||||
|
||||
### Google Gemini
|
||||
- **Images**: Max 100 MB
|
||||
- **PDFs**: Max 50 MB
|
||||
- **Audio**: Max 100 MB, up to 9.5 hours
|
||||
- **Video**: Max 2 GB, up to 1 hour
|
||||
|
||||
### AWS Bedrock
|
||||
- **Images**: Max 4.5 MB, max 8000x8000 pixels
|
||||
- **PDFs**: Max 3.75 MB, up to 100 pages
|
||||
|
||||
## Referencing Files in Prompts
|
||||
|
||||
Use the file's key name in your task descriptions to reference files:
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="""
|
||||
Analyze the provided materials:
|
||||
1. Review the chart in {sales_chart}
|
||||
2. Cross-reference with data in {quarterly_report}
|
||||
3. Summarize key findings
|
||||
""",
|
||||
expected_output="Analysis summary with key insights",
|
||||
input_files={
|
||||
"sales_chart": ImageFile(source="chart.png"),
|
||||
"quarterly_report": PDFFile(source="report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -207,6 +207,37 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
| o3-mini | 200,000 tokens | Lightweight reasoning model |
|
||||
| o4-mini | 200,000 tokens | Next-gen efficient reasoning |
|
||||
|
||||
**Responses API:**
|
||||
|
||||
OpenAI offers two APIs: Chat Completions (default) and the newer Responses API. The Responses API was designed from the ground up with native multimodal support—text, images, audio, and function calls are all first-class citizens. It provides better performance with reasoning models and supports additional features like auto-chaining and built-in tools.
|
||||
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
# Use the Responses API instead of Chat Completions
|
||||
llm = LLM(
|
||||
model="openai/gpt-4o",
|
||||
api="responses", # Enable Responses API
|
||||
store=True, # Store responses for multi-turn (optional)
|
||||
auto_chain=True, # Auto-chain for reasoning models (optional)
|
||||
)
|
||||
```
|
||||
|
||||
**Responses API Parameters:**
|
||||
- `api`: Set to `"responses"` to use the Responses API (default: `"completions"`)
|
||||
- `instructions`: System-level instructions (Responses API only)
|
||||
- `store`: Whether to store responses for multi-turn conversations
|
||||
- `previous_response_id`: ID of previous response for multi-turn
|
||||
- `include`: Additional data to include in response (e.g., `["reasoning.encrypted_content"]`)
|
||||
- `builtin_tools`: List of OpenAI built-in tools: `"web_search"`, `"file_search"`, `"code_interpreter"`, `"computer_use"`
|
||||
- `parse_tool_outputs`: Return structured `ResponsesAPIResult` with parsed built-in tool outputs
|
||||
- `auto_chain`: Automatically track and use response IDs for multi-turn conversations
|
||||
- `auto_chain_reasoning`: Track encrypted reasoning items for ZDR (Zero Data Retention) compliance
|
||||
|
||||
<Tip>
|
||||
Use the Responses API for new projects, especially when working with reasoning models (o1, o3, o4) or when you need native multimodal support for [files](/en/concepts/files).
|
||||
</Tip>
|
||||
|
||||
**Note:** To use OpenAI, install the required dependencies:
|
||||
```bash
|
||||
uv add "crewai[openai]"
|
||||
@@ -375,10 +406,13 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
GEMINI_API_KEY=<your-api-key>
|
||||
|
||||
# Optional - for Vertex AI
|
||||
# For Vertex AI Express mode (API key authentication)
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
|
||||
# For Vertex AI with service account
|
||||
GOOGLE_CLOUD_PROJECT=<your-project-id>
|
||||
GOOGLE_CLOUD_LOCATION=<location> # Defaults to us-central1
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true # Set to use Vertex AI
|
||||
```
|
||||
|
||||
**Basic Usage:**
|
||||
@@ -412,7 +446,35 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
)
|
||||
```
|
||||
|
||||
**Vertex AI Configuration:**
|
||||
**Vertex AI Express Mode (API Key Authentication):**
|
||||
|
||||
Vertex AI Express mode allows you to use Vertex AI with simple API key authentication instead of service account credentials. This is the quickest way to get started with Vertex AI.
|
||||
|
||||
To enable Express mode, set both environment variables in your `.env` file:
|
||||
```toml .env
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
```
|
||||
|
||||
Then use the LLM as usual:
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
llm = LLM(
|
||||
model="gemini/gemini-2.0-flash",
|
||||
temperature=0.7
|
||||
)
|
||||
```
|
||||
|
||||
<Info>
|
||||
To get an Express mode API key:
|
||||
- New Google Cloud users: Get an [express mode API key](https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey)
|
||||
- Existing Google Cloud users: Get a [Google Cloud API key bound to a service account](https://cloud.google.com/docs/authentication/api-keys)
|
||||
|
||||
For more details, see the [Vertex AI Express mode documentation](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey).
|
||||
</Info>
|
||||
|
||||
**Vertex AI Configuration (Service Account):**
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
@@ -424,10 +486,10 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
```
|
||||
|
||||
**Supported Environment Variables:**
|
||||
- `GOOGLE_API_KEY` or `GEMINI_API_KEY`: Your Google API key (required for Gemini API)
|
||||
- `GOOGLE_CLOUD_PROJECT`: Google Cloud project ID (for Vertex AI)
|
||||
- `GOOGLE_API_KEY` or `GEMINI_API_KEY`: Your Google API key (required for Gemini API and Vertex AI Express mode)
|
||||
- `GOOGLE_GENAI_USE_VERTEXAI`: Set to `true` to use Vertex AI (required for Express mode)
|
||||
- `GOOGLE_CLOUD_PROJECT`: Google Cloud project ID (for Vertex AI with service account)
|
||||
- `GOOGLE_CLOUD_LOCATION`: GCP location (defaults to `us-central1`)
|
||||
- `GOOGLE_GENAI_USE_VERTEXAI`: Set to `true` to use Vertex AI
|
||||
|
||||
**Features:**
|
||||
- Native function calling support for Gemini 1.5+ and 2.x models
|
||||
|
||||
@@ -401,23 +401,58 @@ crew = Crew(
|
||||
|
||||
### Vertex AI Embeddings
|
||||
|
||||
For Google Cloud users with Vertex AI access.
|
||||
For Google Cloud users with Vertex AI access. Supports both legacy and new embedding models with automatic SDK selection.
|
||||
|
||||
<Note>
|
||||
**Deprecation Notice:** Legacy models (`textembedding-gecko*`) use the deprecated `vertexai.language_models` SDK which will be removed after June 24, 2026. Consider migrating to newer models like `gemini-embedding-001`. See the [Google migration guide](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/deprecations/genai-vertexai-sdk) for details.
|
||||
</Note>
|
||||
|
||||
```python
|
||||
# Recommended: Using new models with google-genai SDK
|
||||
crew = Crew(
|
||||
memory=True,
|
||||
embedder={
|
||||
"provider": "vertexai",
|
||||
"provider": "google-vertex",
|
||||
"config": {
|
||||
"project_id": "your-gcp-project-id",
|
||||
"region": "us-central1", # or your preferred region
|
||||
"api_key": "your-service-account-key",
|
||||
"model_name": "textembedding-gecko"
|
||||
"location": "us-central1",
|
||||
"model_name": "gemini-embedding-001", # or "text-embedding-005", "text-multilingual-embedding-002"
|
||||
"task_type": "RETRIEVAL_DOCUMENT", # Optional
|
||||
"output_dimensionality": 768 # Optional
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
# Using API key authentication (Exp)
|
||||
crew = Crew(
|
||||
memory=True,
|
||||
embedder={
|
||||
"provider": "google-vertex",
|
||||
"config": {
|
||||
"api_key": "your-google-api-key",
|
||||
"model_name": "gemini-embedding-001"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
# Legacy models (backwards compatible, emits deprecation warning)
|
||||
crew = Crew(
|
||||
memory=True,
|
||||
embedder={
|
||||
"provider": "google-vertex",
|
||||
"config": {
|
||||
"project_id": "your-gcp-project-id",
|
||||
"region": "us-central1", # or "location" (region is deprecated)
|
||||
"model_name": "textembedding-gecko" # Legacy model
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Available models:**
|
||||
- **New SDK models** (recommended): `gemini-embedding-001`, `text-embedding-005`, `text-multilingual-embedding-002`
|
||||
- **Legacy models** (deprecated): `textembedding-gecko`, `textembedding-gecko@001`, `textembedding-gecko-multilingual`
|
||||
|
||||
### Ollama Embeddings (Local)
|
||||
|
||||
Run embeddings locally for privacy and cost savings.
|
||||
@@ -569,7 +604,7 @@ mem0_client_embedder_config = {
|
||||
"project_id": "my_project_id", # Optional
|
||||
"api_key": "custom-api-key" # Optional - overrides env var
|
||||
"run_id": "my_run_id", # Optional - for short-term memory
|
||||
"includes": "include1", # Optional
|
||||
"includes": "include1", # Optional
|
||||
"excludes": "exclude1", # Optional
|
||||
"infer": True # Optional defaults to True
|
||||
"custom_categories": new_categories # Optional - custom categories for user memory
|
||||
@@ -591,7 +626,7 @@ crew = Crew(
|
||||
|
||||
### Choosing the Right Embedding Provider
|
||||
|
||||
When selecting an embedding provider, consider factors like performance, privacy, cost, and integration needs.
|
||||
When selecting an embedding provider, consider factors like performance, privacy, cost, and integration needs.
|
||||
Below is a comparison to help you decide:
|
||||
|
||||
| Provider | Best For | Pros | Cons |
|
||||
@@ -749,7 +784,7 @@ Entity Memory supports batching when saving multiple entities at once. When you
|
||||
|
||||
This improves performance and observability when writing many entities in one operation.
|
||||
|
||||
## 2. External Memory
|
||||
## 2. External Memory
|
||||
External Memory provides a standalone memory system that operates independently from the crew's built-in memory. This is ideal for specialized memory providers or cross-application memory sharing.
|
||||
|
||||
### Basic External Memory with Mem0
|
||||
@@ -819,7 +854,7 @@ external_memory = ExternalMemory(
|
||||
"project_id": "my_project_id", # Optional
|
||||
"api_key": "custom-api-key" # Optional - overrides env var
|
||||
"run_id": "my_run_id", # Optional - for short-term memory
|
||||
"includes": "include1", # Optional
|
||||
"includes": "include1", # Optional
|
||||
"excludes": "exclude1", # Optional
|
||||
"infer": True # Optional defaults to True
|
||||
"custom_categories": new_categories # Optional - custom categories for user memory
|
||||
|
||||
@@ -46,7 +46,7 @@ crew = Crew(
|
||||
## Task Attributes
|
||||
|
||||
| Attribute | Parameters | Type | Description |
|
||||
| :------------------------------------- | :---------------------- | :-------------------------- | :-------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| :------------------------------------- | :---------------------- | :-------------------------- | :-------------------------------------------------------------------------------------------------------------- |
|
||||
| **Description** | `description` | `str` | A clear, concise statement of what the task entails. |
|
||||
| **Expected Output** | `expected_output` | `str` | A detailed description of what the task's completion looks like. |
|
||||
| **Name** _(optional)_ | `name` | `Optional[str]` | A name identifier for the task. |
|
||||
@@ -63,7 +63,7 @@ crew = Crew(
|
||||
| **Output Pydantic** _(optional)_ | `output_pydantic` | `Optional[Type[BaseModel]]` | A Pydantic model for task output. |
|
||||
| **Callback** _(optional)_ | `callback` | `Optional[Any]` | Function/object to be executed after task completion. |
|
||||
| **Guardrail** _(optional)_ | `guardrail` | `Optional[Callable]` | Function to validate task output before proceeding to next task. |
|
||||
| **Guardrails** _(optional)_ | `guardrails` | `Optional[List[Callable] | List[str]]` | List of guardrails to validate task output before proceeding to next task. |
|
||||
| **Guardrails** _(optional)_ | `guardrails` | `Optional[List[Callable]]` | List of guardrails to validate task output before proceeding to next task. |
|
||||
| **Guardrail Max Retries** _(optional)_ | `guardrail_max_retries` | `Optional[int]` | Maximum number of retries when guardrail validation fails. Defaults to 3. |
|
||||
|
||||
<Note type="warning" title="Deprecated: max_retries">
|
||||
|
||||
563
docs/en/enterprise/features/flow-hitl-management.mdx
Normal file
@@ -0,0 +1,563 @@
|
||||
---
|
||||
title: "Flow HITL Management"
|
||||
description: "Enterprise-grade human review for Flows with email-first notifications, routing rules, and auto-response capabilities"
|
||||
icon: "users-gear"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Flow HITL Management features require the `@human_feedback` decorator, available in **CrewAI version 1.8.0 or higher**. These features apply specifically to **Flows**, not Crews.
|
||||
</Note>
|
||||
|
||||
CrewAI Enterprise provides a comprehensive Human-in-the-Loop (HITL) management system for Flows that transforms AI workflows into collaborative human-AI processes. The platform uses an **email-first architecture** that enables anyone with an email address to respond to review requests—no platform account required.
|
||||
|
||||
## Overview
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Email-First Design" icon="envelope">
|
||||
Responders can reply directly to notification emails to provide feedback
|
||||
</Card>
|
||||
<Card title="Flexible Routing" icon="route">
|
||||
Route requests to specific emails based on method patterns or flow state
|
||||
</Card>
|
||||
<Card title="Auto-Response" icon="clock">
|
||||
Configure automatic fallback responses when no human replies in time
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Key Benefits
|
||||
|
||||
- **Simple mental model**: Email addresses are universal; no need to manage platform users or roles
|
||||
- **External responders**: Anyone with an email can respond, even non-platform users
|
||||
- **Dynamic assignment**: Pull assignee email directly from flow state (e.g., `sales_rep_email`)
|
||||
- **Reduced configuration**: Fewer settings to configure, faster time to value
|
||||
- **Email as primary channel**: Most users prefer responding via email over logging into a dashboard
|
||||
|
||||
## Setting Up Human Review Points in Flows
|
||||
|
||||
Configure human review checkpoints within your Flows using the `@human_feedback` decorator. When execution reaches a review point, the system pauses, notifies the assignee via email, and waits for a response.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start, listen
|
||||
from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult
|
||||
|
||||
class ContentApprovalFlow(Flow):
|
||||
@start()
|
||||
def generate_content(self):
|
||||
# AI generates content
|
||||
return "Generated marketing copy for Q1 campaign..."
|
||||
|
||||
@listen(generate_content)
|
||||
@human_feedback(
|
||||
message="Please review this content for brand compliance:",
|
||||
emit=["approved", "rejected", "needs_revision"],
|
||||
)
|
||||
def review_content(self, content):
|
||||
return content
|
||||
|
||||
@listen("approved")
|
||||
def publish_content(self, result: HumanFeedbackResult):
|
||||
print(f"Publishing approved content. Reviewer notes: {result.feedback}")
|
||||
|
||||
@listen("rejected")
|
||||
def archive_content(self, result: HumanFeedbackResult):
|
||||
print(f"Content rejected. Reason: {result.feedback}")
|
||||
|
||||
@listen("needs_revision")
|
||||
def revise_content(self, result: HumanFeedbackResult):
|
||||
print(f"Revision requested: {result.feedback}")
|
||||
```
|
||||
|
||||
For complete implementation details, see the [Human Feedback in Flows](/en/learn/human-feedback-in-flows) guide.
|
||||
|
||||
### Decorator Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `message` | `str` | The message displayed to the human reviewer |
|
||||
| `emit` | `list[str]` | Valid response options (displayed as buttons in UI) |
|
||||
|
||||
## Platform Configuration
|
||||
|
||||
Access HITL configuration from: **Deployment → Settings → Human in the Loop Configuration**
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-overview.png" alt="HITL Configuration Settings" />
|
||||
</Frame>
|
||||
|
||||
### Email Notifications
|
||||
|
||||
Toggle to enable or disable email notifications for HITL requests.
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| Email Notifications | Enabled | Send emails when feedback is requested |
|
||||
|
||||
<Note>
|
||||
When disabled, responders must use the dashboard UI or you must configure webhooks for custom notification systems.
|
||||
</Note>
|
||||
|
||||
### SLA Target
|
||||
|
||||
Set a target response time for tracking and metrics purposes.
|
||||
|
||||
| Setting | Description |
|
||||
|---------|-------------|
|
||||
| SLA Target (minutes) | Target response time. Used for dashboard metrics and SLA tracking |
|
||||
|
||||
Leave empty to disable SLA tracking.
|
||||
|
||||
## Email Notifications & Responses
|
||||
|
||||
The HITL system uses an email-first architecture where responders can reply directly to notification emails.
|
||||
|
||||
### How Email Responses Work
|
||||
|
||||
<Steps>
|
||||
<Step title="Notification Sent">
|
||||
When a HITL request is created, an email is sent to the assigned responder with the review content and context.
|
||||
</Step>
|
||||
<Step title="Reply-To Address">
|
||||
The email includes a special reply-to address with a signed token for authentication.
|
||||
</Step>
|
||||
<Step title="User Replies">
|
||||
The responder simply replies to the email with their feedback—no login required.
|
||||
</Step>
|
||||
<Step title="Token Validation">
|
||||
The platform receives the reply, verifies the signed token, and matches the sender email.
|
||||
</Step>
|
||||
<Step title="Flow Resumes">
|
||||
The feedback is recorded and the flow continues with the human's input.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Response Format
|
||||
|
||||
Responders can reply with:
|
||||
|
||||
- **Emit option**: If the reply matches an `emit` option (e.g., "approved"), it's used directly
|
||||
- **Free-form text**: Any text response is passed to the flow as feedback
|
||||
- **Plain text**: The first line of the reply body is used as feedback
|
||||
|
||||
### Confirmation Emails
|
||||
|
||||
After processing a reply, the responder receives a confirmation email indicating whether the feedback was successfully submitted or if an error occurred.
|
||||
|
||||
### Email Token Security
|
||||
|
||||
- Tokens are cryptographically signed for security
|
||||
- Tokens expire after 7 days
|
||||
- Sender email must match the token's authorized email
|
||||
- Confirmation/error emails are sent after processing
|
||||
|
||||
## Routing Rules
|
||||
|
||||
Route HITL requests to specific email addresses based on method patterns.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-routing-rules.png" alt="HITL Routing Rules Configuration" />
|
||||
</Frame>
|
||||
|
||||
### Rule Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Approvals to Finance",
|
||||
"match": {
|
||||
"method_name": "approve_*"
|
||||
},
|
||||
"assign_to_email": "finance@company.com",
|
||||
"assign_from_input": "manager_email"
|
||||
}
|
||||
```
|
||||
|
||||
### Matching Patterns
|
||||
|
||||
| Pattern | Description | Example Match |
|
||||
|---------|-------------|---------------|
|
||||
| `approve_*` | Wildcard (any chars) | `approve_payment`, `approve_vendor` |
|
||||
| `review_?` | Single char | `review_a`, `review_1` |
|
||||
| `validate_payment` | Exact match | `validate_payment` only |
|
||||
|
||||
### Assignment Priority
|
||||
|
||||
1. **Dynamic assignment** (`assign_from_input`): If configured, pulls email from flow state
|
||||
2. **Static email** (`assign_to_email`): Falls back to configured email
|
||||
3. **Deployment creator**: If no rule matches, the deployment creator's email is used
|
||||
|
||||
### Dynamic Assignment Example
|
||||
|
||||
If your flow state contains `{"sales_rep_email": "alice@company.com"}`, configure:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Route to Sales Rep",
|
||||
"match": {
|
||||
"method_name": "review_*"
|
||||
},
|
||||
"assign_from_input": "sales_rep_email"
|
||||
}
|
||||
```
|
||||
|
||||
The request will be assigned to `alice@company.com` automatically.
|
||||
|
||||
<Tip>
|
||||
**Use Case**: Pull the assignee from your CRM, database, or previous flow step to dynamically route reviews to the right person.
|
||||
</Tip>
|
||||
|
||||
## Auto-Response
|
||||
|
||||
Automatically respond to HITL requests if no human responds within a timeout. This ensures flows don't hang indefinitely.
|
||||
|
||||
### Configuration
|
||||
|
||||
| Setting | Description |
|
||||
|---------|-------------|
|
||||
| Enabled | Toggle to enable auto-response |
|
||||
| Timeout (minutes) | Time to wait before auto-responding |
|
||||
| Default Outcome | The response value (must match an `emit` option) |
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-auto-respond.png" alt="HITL Auto-Response Configuration" />
|
||||
</Frame>
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **SLA compliance**: Ensure flows don't hang indefinitely
|
||||
- **Default approval**: Auto-approve low-risk requests after timeout
|
||||
- **Graceful degradation**: Continue with a safe default when reviewers are unavailable
|
||||
|
||||
<Warning>
|
||||
Use auto-response carefully. Only enable it for non-critical reviews where a default response is acceptable.
|
||||
</Warning>
|
||||
|
||||
## Review Process
|
||||
|
||||
### Dashboard Interface
|
||||
|
||||
The HITL review interface provides a clean, focused experience for reviewers:
|
||||
|
||||
- **Markdown Rendering**: Rich formatting for review content with syntax highlighting
|
||||
- **Context Panel**: View flow state, execution history, and related information
|
||||
- **Feedback Input**: Provide detailed feedback and comments with your decision
|
||||
- **Quick Actions**: One-click emit option buttons with optional comments
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-list-pending-feedbacks.png" alt="HITL Pending Requests List" />
|
||||
</Frame>
|
||||
|
||||
### Response Methods
|
||||
|
||||
Reviewers can respond via three channels:
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| **Email Reply** | Reply directly to the notification email |
|
||||
| **Dashboard** | Use the Enterprise dashboard UI |
|
||||
| **API/Webhook** | Programmatic response via API |
|
||||
|
||||
### History & Audit Trail
|
||||
|
||||
Every HITL interaction is tracked with a complete timeline:
|
||||
|
||||
- Decision history (approve/reject/revise)
|
||||
- Reviewer identity and timestamp
|
||||
- Feedback and comments provided
|
||||
- Response method (email/dashboard/API)
|
||||
- Response time metrics
|
||||
|
||||
## Analytics & Monitoring
|
||||
|
||||
Track HITL performance with comprehensive analytics.
|
||||
|
||||
### Performance Dashboard
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-metrics.png" alt="HITL Metrics Dashboard" />
|
||||
</Frame>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Response Times" icon="stopwatch">
|
||||
Monitor average and median response times by reviewer or flow.
|
||||
</Card>
|
||||
<Card title="Volume Trends" icon="chart-bar">
|
||||
Analyze review volume patterns to optimize team capacity.
|
||||
</Card>
|
||||
<Card title="Decision Distribution" icon="chart-pie">
|
||||
View approval/rejection rates across different review types.
|
||||
</Card>
|
||||
<Card title="SLA Tracking" icon="chart-line">
|
||||
Track percentage of reviews completed within SLA targets.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Audit & Compliance
|
||||
|
||||
Enterprise-ready audit capabilities for regulatory requirements:
|
||||
|
||||
- Complete decision history with timestamps
|
||||
- Reviewer identity verification
|
||||
- Immutable audit logs
|
||||
- Export capabilities for compliance reporting
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Security Reviews" icon="shield-halved">
|
||||
**Use Case**: Internal security questionnaire automation with human validation
|
||||
|
||||
- AI generates responses to security questionnaires
|
||||
- Security team reviews and validates accuracy via email
|
||||
- Approved responses are compiled into final submission
|
||||
- Full audit trail for compliance
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Content Approval" icon="file-lines">
|
||||
**Use Case**: Marketing content requiring legal/brand review
|
||||
|
||||
- AI generates marketing copy or social media content
|
||||
- Route to brand team email for voice/tone review
|
||||
- Automatic publishing upon approval
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Financial Approvals" icon="money-bill">
|
||||
**Use Case**: Expense reports, contract terms, budget allocations
|
||||
|
||||
- AI pre-processes and categorizes financial requests
|
||||
- Route based on amount thresholds using dynamic assignment
|
||||
- Maintain complete audit trail for financial compliance
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Dynamic Assignment from CRM" icon="database">
|
||||
**Use Case**: Route reviews to account owners from your CRM
|
||||
|
||||
- Flow fetches account owner email from CRM
|
||||
- Store email in flow state (e.g., `account_owner_email`)
|
||||
- Use `assign_from_input` to route to the right person automatically
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Quality Assurance" icon="magnifying-glass">
|
||||
**Use Case**: AI output validation before customer delivery
|
||||
|
||||
- AI generates customer-facing content or responses
|
||||
- QA team reviews via email notification
|
||||
- Feedback loops improve AI performance over time
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Webhooks API
|
||||
|
||||
When your Flows pause for human feedback, you can configure webhooks to send request data to your own application. This enables:
|
||||
|
||||
- Building custom approval UIs
|
||||
- Integrating with internal tools (Jira, ServiceNow, custom dashboards)
|
||||
- Routing approvals to third-party systems
|
||||
- Mobile app notifications
|
||||
- Automated decision systems
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-webhook.png" alt="HITL Webhook Configuration" />
|
||||
</Frame>
|
||||
|
||||
### Configuring Webhooks
|
||||
|
||||
<Steps>
|
||||
<Step title="Navigate to Settings">
|
||||
Go to your **Deployment** → **Settings** → **Human in the Loop**
|
||||
</Step>
|
||||
<Step title="Expand Webhooks Section">
|
||||
Click to expand the **Webhooks** configuration
|
||||
</Step>
|
||||
<Step title="Add Your Webhook URL">
|
||||
Enter your webhook URL (must be HTTPS in production)
|
||||
</Step>
|
||||
<Step title="Save Configuration">
|
||||
Click **Save Configuration** to activate
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
You can configure multiple webhooks. Each active webhook receives all HITL events.
|
||||
|
||||
### Webhook Events
|
||||
|
||||
Your endpoint will receive HTTP POST requests for these events:
|
||||
|
||||
| Event Type | When Triggered |
|
||||
|------------|----------------|
|
||||
| `new_request` | A flow pauses and requests human feedback |
|
||||
|
||||
### Webhook Payload
|
||||
|
||||
All webhooks receive a JSON payload with this structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "new_request",
|
||||
"request": {
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"flow_id": "flow_abc123",
|
||||
"method_name": "review_article",
|
||||
"message": "Please review this article for publication.",
|
||||
"emit_options": ["approved", "rejected", "request_changes"],
|
||||
"state": {
|
||||
"article_id": 12345,
|
||||
"author": "john@example.com",
|
||||
"category": "technology"
|
||||
},
|
||||
"metadata": {},
|
||||
"created_at": "2026-01-14T12:00:00Z"
|
||||
},
|
||||
"deployment": {
|
||||
"id": 456,
|
||||
"name": "Content Review Flow",
|
||||
"organization_id": 789
|
||||
},
|
||||
"callback_url": "https://api.crewai.com/...",
|
||||
"assigned_to_email": "reviewer@company.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Responding to Requests
|
||||
|
||||
To submit feedback, **POST to the `callback_url`** included in the webhook payload.
|
||||
|
||||
```http
|
||||
POST {callback_url}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"feedback": "Approved. Great article!",
|
||||
"source": "my_custom_app"
|
||||
}
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
<Info>
|
||||
All webhook requests are cryptographically signed using HMAC-SHA256 to ensure authenticity and prevent tampering.
|
||||
</Info>
|
||||
|
||||
#### Webhook Security
|
||||
|
||||
- **HMAC-SHA256 signatures**: Every webhook includes a cryptographic signature
|
||||
- **Per-webhook secrets**: Each webhook has its own unique signing secret
|
||||
- **Encrypted at rest**: Signing secrets are encrypted in our database
|
||||
- **Timestamp verification**: Prevents replay attacks
|
||||
|
||||
#### Signature Headers
|
||||
|
||||
Each webhook request includes these headers:
|
||||
|
||||
| Header | Description |
|
||||
|--------|-------------|
|
||||
| `X-Signature` | HMAC-SHA256 signature: `sha256=<hex_digest>` |
|
||||
| `X-Timestamp` | Unix timestamp when the request was signed |
|
||||
|
||||
#### Verification
|
||||
|
||||
Verify by computing:
|
||||
|
||||
```python
|
||||
import hmac
|
||||
import hashlib
|
||||
|
||||
expected = hmac.new(
|
||||
signing_secret.encode(),
|
||||
f"{timestamp}.{payload}".encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
if hmac.compare_digest(expected, signature):
|
||||
# Valid signature
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Your webhook endpoint should return a 2xx status code to acknowledge receipt:
|
||||
|
||||
| Your Response | Our Behavior |
|
||||
|---------------|--------------|
|
||||
| 2xx | Webhook delivered successfully |
|
||||
| 4xx/5xx | Logged as failed, no retry |
|
||||
| Timeout (30s) | Logged as failed, no retry |
|
||||
|
||||
## Security & RBAC
|
||||
|
||||
### Dashboard Access
|
||||
|
||||
HITL access is controlled at the deployment level:
|
||||
|
||||
| Permission | Capability |
|
||||
|------------|------------|
|
||||
| `manage_human_feedback` | Configure HITL settings, view all requests |
|
||||
| `respond_to_human_feedback` | Respond to requests, view assigned requests |
|
||||
|
||||
### Email Response Authorization
|
||||
|
||||
For email replies:
|
||||
1. The reply-to token encodes the authorized email
|
||||
2. Sender email must match the token's email
|
||||
3. Token must not be expired (7-day default)
|
||||
4. Request must still be pending
|
||||
|
||||
### Audit Trail
|
||||
|
||||
All HITL actions are logged:
|
||||
- Request creation
|
||||
- Assignment changes
|
||||
- Response submission (with source: dashboard/email/API)
|
||||
- Flow resume status
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Emails Not Sending
|
||||
|
||||
1. Check "Email Notifications" is enabled in configuration
|
||||
2. Verify routing rules match the method name
|
||||
3. Verify assignee email is valid
|
||||
4. Check deployment creator fallback if no routing rules match
|
||||
|
||||
### Email Replies Not Processing
|
||||
|
||||
1. Check token hasn't expired (7-day default)
|
||||
2. Verify sender email matches assigned email
|
||||
3. Ensure request is still pending (not already responded)
|
||||
|
||||
### Flow Not Resuming
|
||||
|
||||
1. Check request status in dashboard
|
||||
2. Verify callback URL is accessible
|
||||
3. Ensure deployment is still running
|
||||
|
||||
## Best Practices
|
||||
|
||||
<Tip>
|
||||
**Start Simple**: Begin with email notifications to deployment creator, then add routing rules as your workflows mature.
|
||||
</Tip>
|
||||
|
||||
1. **Use Dynamic Assignment**: Pull assignee emails from your flow state for flexible routing.
|
||||
|
||||
2. **Configure Auto-Response**: Set up a fallback for non-critical reviews to prevent flows from hanging.
|
||||
|
||||
3. **Monitor Response Times**: Use analytics to identify bottlenecks and optimize your review process.
|
||||
|
||||
4. **Keep Review Messages Clear**: Write clear, actionable messages in the `@human_feedback` decorator.
|
||||
|
||||
5. **Test Email Flow**: Send test requests to verify email delivery before going to production.
|
||||
|
||||
## Related Resources
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Human Feedback in Flows" icon="code" href="/en/learn/human-feedback-in-flows">
|
||||
Implementation guide for the `@human_feedback` decorator
|
||||
</Card>
|
||||
<Card title="Flow HITL Workflow Guide" icon="route" href="/en/enterprise/guides/human-in-the-loop">
|
||||
Step-by-step guide for setting up HITL workflows
|
||||
</Card>
|
||||
<Card title="RBAC Configuration" icon="shield-check" href="/en/enterprise/features/rbac">
|
||||
Configure role-based access control for your organization
|
||||
</Card>
|
||||
<Card title="Webhook Streaming" icon="bolt" href="/en/enterprise/features/webhook-streaming">
|
||||
Set up real-time event notifications
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: "Deploy Crew"
|
||||
description: "Deploying a Crew on CrewAI AMP"
|
||||
title: "Deploy to AMP"
|
||||
description: "Deploy your Crew or Flow to CrewAI AMP"
|
||||
icon: "rocket"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
After creating a crew locally or through Crew Studio, the next step is
|
||||
After creating a Crew or Flow locally (or through Crew Studio), the next step is
|
||||
deploying it to the CrewAI AMP platform. This guide covers multiple deployment
|
||||
methods to help you choose the best approach for your workflow.
|
||||
</Note>
|
||||
@@ -14,19 +14,26 @@ mode: "wide"
|
||||
## Prerequisites
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Crew Ready for Deployment" icon="users">
|
||||
You should have a working crew either built locally or created through Crew
|
||||
Studio
|
||||
<Card title="Project Ready for Deployment" icon="check-circle">
|
||||
You should have a working Crew or Flow that runs successfully locally.
|
||||
Follow our [preparation guide](/en/enterprise/guides/prepare-for-deployment) to verify your project structure.
|
||||
</Card>
|
||||
<Card title="GitHub Repository" icon="github">
|
||||
Your crew code should be in a GitHub repository (for GitHub integration
|
||||
Your code should be in a GitHub repository (for GitHub integration
|
||||
method)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Info>
|
||||
**Crews vs Flows**: Both project types can be deployed as "automations" on CrewAI AMP.
|
||||
The deployment process is the same, but they have different project structures.
|
||||
See [Prepare for Deployment](/en/enterprise/guides/prepare-for-deployment) for details.
|
||||
</Info>
|
||||
|
||||
## Option 1: Deploy Using CrewAI CLI
|
||||
|
||||
The CLI provides the fastest way to deploy locally developed crews to the Enterprise platform.
|
||||
The CLI provides the fastest way to deploy locally developed Crews or Flows to the AMP platform.
|
||||
The CLI automatically detects your project type from `pyproject.toml` and builds accordingly.
|
||||
|
||||
<Steps>
|
||||
<Step title="Install CrewAI CLI">
|
||||
@@ -128,7 +135,7 @@ crewai deploy remove <deployment_id>
|
||||
|
||||
## Option 2: Deploy Directly via Web Interface
|
||||
|
||||
You can also deploy your crews directly through the CrewAI AMP web interface by connecting your GitHub account. This approach doesn't require using the CLI on your local machine.
|
||||
You can also deploy your Crews or Flows directly through the CrewAI AMP web interface by connecting your GitHub account. This approach doesn't require using the CLI on your local machine. The platform automatically detects your project type and handles the build appropriately.
|
||||
|
||||
<Steps>
|
||||
|
||||
@@ -282,68 +289,7 @@ For automated deployments in CI/CD pipelines, you can use the CrewAI API to trig
|
||||
|
||||
</Steps>
|
||||
|
||||
## ⚠️ Environment Variable Security Requirements
|
||||
|
||||
<Warning>
|
||||
**Important**: CrewAI AMP has security restrictions on environment variable
|
||||
names that can cause deployment failures if not followed.
|
||||
</Warning>
|
||||
|
||||
### Blocked Environment Variable Patterns
|
||||
|
||||
For security reasons, the following environment variable naming patterns are **automatically filtered** and will cause deployment issues:
|
||||
|
||||
**Blocked Patterns:**
|
||||
|
||||
- Variables ending with `_TOKEN` (e.g., `MY_API_TOKEN`)
|
||||
- Variables ending with `_PASSWORD` (e.g., `DB_PASSWORD`)
|
||||
- Variables ending with `_SECRET` (e.g., `API_SECRET`)
|
||||
- Variables ending with `_KEY` in certain contexts
|
||||
|
||||
**Specific Blocked Variables:**
|
||||
|
||||
- `GITHUB_USER`, `GITHUB_TOKEN`
|
||||
- `AWS_REGION`, `AWS_DEFAULT_REGION`
|
||||
- Various internal CrewAI system variables
|
||||
|
||||
### Allowed Exceptions
|
||||
|
||||
Some variables are explicitly allowed despite matching blocked patterns:
|
||||
|
||||
- `AZURE_AD_TOKEN`
|
||||
- `AZURE_OPENAI_AD_TOKEN`
|
||||
- `ENTERPRISE_ACTION_TOKEN`
|
||||
- `CREWAI_ENTEPRISE_TOOLS_TOKEN`
|
||||
|
||||
### How to Fix Naming Issues
|
||||
|
||||
If your deployment fails due to environment variable restrictions:
|
||||
|
||||
```bash
|
||||
# ❌ These will cause deployment failures
|
||||
OPENAI_TOKEN=sk-...
|
||||
DATABASE_PASSWORD=mypassword
|
||||
API_SECRET=secret123
|
||||
|
||||
# ✅ Use these naming patterns instead
|
||||
OPENAI_API_KEY=sk-...
|
||||
DATABASE_CREDENTIALS=mypassword
|
||||
API_CONFIG=secret123
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Use standard naming conventions**: `PROVIDER_API_KEY` instead of `PROVIDER_TOKEN`
|
||||
2. **Test locally first**: Ensure your crew works with the renamed variables
|
||||
3. **Update your code**: Change any references to the old variable names
|
||||
4. **Document changes**: Keep track of renamed variables for your team
|
||||
|
||||
<Tip>
|
||||
If you encounter deployment failures with cryptic environment variable errors,
|
||||
check your variable names against these patterns first.
|
||||
</Tip>
|
||||
|
||||
### Interact with Your Deployed Crew
|
||||
## Interact with Your Deployed Automation
|
||||
|
||||
Once deployment is complete, you can access your crew through:
|
||||
|
||||
@@ -387,7 +333,108 @@ The Enterprise platform also offers:
|
||||
- **Custom Tools Repository**: Create, share, and install tools
|
||||
- **Crew Studio**: Build crews through a chat interface without writing code
|
||||
|
||||
## Troubleshooting Deployment Failures
|
||||
|
||||
If your deployment fails, check these common issues:
|
||||
|
||||
### Build Failures
|
||||
|
||||
#### Missing uv.lock File
|
||||
|
||||
**Symptom**: Build fails early with dependency resolution errors
|
||||
|
||||
**Solution**: Generate and commit the lock file:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The `uv.lock` file is required for all deployments. Without it, the platform
|
||||
cannot reliably install your dependencies.
|
||||
</Warning>
|
||||
|
||||
#### Wrong Project Structure
|
||||
|
||||
**Symptom**: "Could not find entry point" or "Module not found" errors
|
||||
|
||||
**Solution**: Verify your project matches the expected structure:
|
||||
|
||||
- **Both Crews and Flows**: Must have entry point at `src/project_name/main.py`
|
||||
- **Crews**: Use a `run()` function as entry point
|
||||
- **Flows**: Use a `kickoff()` function as entry point
|
||||
|
||||
See [Prepare for Deployment](/en/enterprise/guides/prepare-for-deployment) for detailed structure diagrams.
|
||||
|
||||
#### Missing CrewBase Decorator
|
||||
|
||||
**Symptom**: "Crew not found", "Config not found", or agent/task configuration errors
|
||||
|
||||
**Solution**: Ensure **all** crew classes use the `@CrewBase` decorator:
|
||||
|
||||
```python
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
|
||||
@CrewBase # This decorator is REQUIRED
|
||||
class YourCrew():
|
||||
"""Your crew description"""
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# ... rest of crew definition
|
||||
```
|
||||
|
||||
<Info>
|
||||
This applies to standalone Crews AND crews embedded inside Flow projects.
|
||||
Every crew class needs the decorator.
|
||||
</Info>
|
||||
|
||||
#### Incorrect pyproject.toml Type
|
||||
|
||||
**Symptom**: Build succeeds but runtime fails, or unexpected behavior
|
||||
|
||||
**Solution**: Verify the `[tool.crewai]` section matches your project type:
|
||||
|
||||
```toml
|
||||
# For Crew projects:
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
|
||||
# For Flow projects:
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
|
||||
### Runtime Failures
|
||||
|
||||
#### LLM Connection Failures
|
||||
|
||||
**Symptom**: API key errors, "model not found", or authentication failures
|
||||
|
||||
**Solution**:
|
||||
1. Verify your LLM provider's API key is correctly set in environment variables
|
||||
2. Ensure the environment variable names match what your code expects
|
||||
3. Test locally with the exact same environment variables before deploying
|
||||
|
||||
#### Crew Execution Errors
|
||||
|
||||
**Symptom**: Crew starts but fails during execution
|
||||
|
||||
**Solution**:
|
||||
1. Check the execution logs in the AMP dashboard (Traces tab)
|
||||
2. Verify all tools have required API keys configured
|
||||
3. Ensure agent configurations in `agents.yaml` are valid
|
||||
4. Check task configurations in `tasks.yaml` for syntax errors
|
||||
|
||||
<Card title="Need Help?" icon="headset" href="mailto:support@crewai.com">
|
||||
Contact our support team for assistance with deployment issues or questions
|
||||
about the Enterprise platform.
|
||||
about the AMP platform.
|
||||
</Card>
|
||||
@@ -5,9 +5,54 @@ icon: "user-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
Human-In-The-Loop (HITL) is a powerful approach that combines artificial intelligence with human expertise to enhance decision-making and improve task outcomes. This guide shows you how to implement HITL within CrewAI.
|
||||
Human-In-The-Loop (HITL) is a powerful approach that combines artificial intelligence with human expertise to enhance decision-making and improve task outcomes. This guide shows you how to implement HITL within CrewAI Enterprise.
|
||||
|
||||
## Setting Up HITL Workflows
|
||||
## HITL Approaches in CrewAI
|
||||
|
||||
CrewAI offers two approaches for implementing human-in-the-loop workflows:
|
||||
|
||||
| Approach | Best For | Version |
|
||||
|----------|----------|---------|
|
||||
| **Flow-based** (`@human_feedback` decorator) | Production with Enterprise UI, email-first workflows, full platform features | **1.8.0+** |
|
||||
| **Webhook-based** | Custom integrations, external systems (Slack, Teams, etc.), legacy setups | All versions |
|
||||
|
||||
## Flow-Based HITL with Enterprise Platform
|
||||
|
||||
<Note>
|
||||
The `@human_feedback` decorator requires **CrewAI version 1.8.0 or higher**.
|
||||
</Note>
|
||||
|
||||
When using the `@human_feedback` decorator in your Flows, CrewAI Enterprise provides an **email-first HITL system** that enables anyone with an email address to respond to review requests:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Email-First Design" icon="envelope">
|
||||
Responders receive email notifications and can reply directly—no login required.
|
||||
</Card>
|
||||
<Card title="Dashboard Review" icon="desktop">
|
||||
Review and respond to HITL requests in the Enterprise dashboard when preferred.
|
||||
</Card>
|
||||
<Card title="Flexible Routing" icon="route">
|
||||
Route requests to specific emails based on method patterns or pull from flow state.
|
||||
</Card>
|
||||
<Card title="Auto-Response" icon="clock">
|
||||
Configure automatic fallback responses when no human replies within the timeout.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Key Benefits
|
||||
|
||||
- **External responders**: Anyone with an email can respond, even non-platform users
|
||||
- **Dynamic assignment**: Pull assignee email from flow state (e.g., `account_owner_email`)
|
||||
- **Simple configuration**: Email-based routing is easier to set up than user/role management
|
||||
- **Deployment creator fallback**: If no routing rule matches, the deployment creator is notified
|
||||
|
||||
<Tip>
|
||||
For implementation details on the `@human_feedback` decorator, see the [Human Feedback in Flows](/en/learn/human-feedback-in-flows) guide.
|
||||
</Tip>
|
||||
|
||||
## Setting Up Webhook-Based HITL Workflows
|
||||
|
||||
For custom integrations with external systems like Slack, Microsoft Teams, or your own applications, you can use the webhook-based approach:
|
||||
|
||||
<Steps>
|
||||
<Step title="Configure Your Task">
|
||||
@@ -99,3 +144,14 @@ HITL workflows are particularly valuable for:
|
||||
- Sensitive or high-stakes operations
|
||||
- Creative tasks requiring human judgment
|
||||
- Compliance and regulatory reviews
|
||||
|
||||
## Learn More
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Flow HITL Management" icon="users-gear" href="/en/enterprise/features/flow-hitl-management">
|
||||
Explore the full Enterprise Flow HITL platform capabilities including email notifications, routing rules, auto-response, and analytics.
|
||||
</Card>
|
||||
<Card title="Human Feedback in Flows" icon="code" href="/en/learn/human-feedback-in-flows">
|
||||
Implementation guide for the `@human_feedback` decorator in your Flows.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
305
docs/en/enterprise/guides/prepare-for-deployment.mdx
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
title: "Prepare for Deployment"
|
||||
description: "Ensure your Crew or Flow is ready for deployment to CrewAI AMP"
|
||||
icon: "clipboard-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Before deploying to CrewAI AMP, it's crucial to verify your project is correctly structured.
|
||||
Both Crews and Flows can be deployed as "automations," but they have different project structures
|
||||
and requirements that must be met for successful deployment.
|
||||
</Note>
|
||||
|
||||
## Understanding Automations
|
||||
|
||||
In CrewAI AMP, **automations** is the umbrella term for deployable Agentic AI projects. An automation can be either:
|
||||
|
||||
- **A Crew**: A standalone team of AI agents working together on tasks
|
||||
- **A Flow**: An orchestrated workflow that can combine multiple crews, direct LLM calls, and procedural logic
|
||||
|
||||
Understanding which type you're deploying is essential because they have different project structures and entry points.
|
||||
|
||||
## Crews vs Flows: Key Differences
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Crew Projects" icon="users">
|
||||
Standalone AI agent teams with `crew.py` defining agents and tasks. Best for focused, collaborative tasks.
|
||||
</Card>
|
||||
<Card title="Flow Projects" icon="diagram-project">
|
||||
Orchestrated workflows with embedded crews in a `crews/` folder. Best for complex, multi-stage processes.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| Aspect | Crew | Flow |
|
||||
|--------|------|------|
|
||||
| **Project structure** | `src/project_name/` with `crew.py` | `src/project_name/` with `crews/` folder |
|
||||
| **Main logic location** | `src/project_name/crew.py` | `src/project_name/main.py` (Flow class) |
|
||||
| **Entry point function** | `run()` in `main.py` | `kickoff()` in `main.py` |
|
||||
| **pyproject.toml type** | `type = "crew"` | `type = "flow"` |
|
||||
| **CLI create command** | `crewai create crew name` | `crewai create flow name` |
|
||||
| **Config location** | `src/project_name/config/` | `src/project_name/crews/crew_name/config/` |
|
||||
| **Can contain other crews** | No | Yes (in `crews/` folder) |
|
||||
|
||||
## Project Structure Reference
|
||||
|
||||
### Crew Project Structure
|
||||
|
||||
When you run `crewai create crew my_crew`, you get this structure:
|
||||
|
||||
```
|
||||
my_crew/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # Must have type = "crew"
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # REQUIRED for deployment
|
||||
└── src/
|
||||
└── my_crew/
|
||||
├── __init__.py
|
||||
├── main.py # Entry point with run() function
|
||||
├── crew.py # Crew class with @CrewBase decorator
|
||||
├── tools/
|
||||
│ ├── custom_tool.py
|
||||
│ └── __init__.py
|
||||
└── config/
|
||||
├── agents.yaml # Agent definitions
|
||||
└── tasks.yaml # Task definitions
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The nested `src/project_name/` structure is critical for Crews.
|
||||
Placing files at the wrong level will cause deployment failures.
|
||||
</Warning>
|
||||
|
||||
### Flow Project Structure
|
||||
|
||||
When you run `crewai create flow my_flow`, you get this structure:
|
||||
|
||||
```
|
||||
my_flow/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # Must have type = "flow"
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # REQUIRED for deployment
|
||||
└── src/
|
||||
└── my_flow/
|
||||
├── __init__.py
|
||||
├── main.py # Entry point with kickoff() function + Flow class
|
||||
├── crews/ # Embedded crews folder
|
||||
│ └── poem_crew/
|
||||
│ ├── __init__.py
|
||||
│ ├── poem_crew.py # Crew with @CrewBase decorator
|
||||
│ └── config/
|
||||
│ ├── agents.yaml
|
||||
│ └── tasks.yaml
|
||||
└── tools/
|
||||
├── __init__.py
|
||||
└── custom_tool.py
|
||||
```
|
||||
|
||||
<Info>
|
||||
Both Crews and Flows use the `src/project_name/` structure.
|
||||
The key difference is that Flows have a `crews/` folder for embedded crews,
|
||||
while Crews have `crew.py` directly in the project folder.
|
||||
</Info>
|
||||
|
||||
## Pre-Deployment Checklist
|
||||
|
||||
Use this checklist to verify your project is ready for deployment.
|
||||
|
||||
### 1. Verify pyproject.toml Configuration
|
||||
|
||||
Your `pyproject.toml` must include the correct `[tool.crewai]` section:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="For Crews">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="For Flows">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
If the `type` doesn't match your project structure, the build will fail or
|
||||
the automation won't run correctly.
|
||||
</Warning>
|
||||
|
||||
### 2. Ensure uv.lock File Exists
|
||||
|
||||
CrewAI uses `uv` for dependency management. The `uv.lock` file ensures reproducible builds and is **required** for deployment.
|
||||
|
||||
```bash
|
||||
# Generate or update the lock file
|
||||
uv lock
|
||||
|
||||
# Verify it exists
|
||||
ls -la uv.lock
|
||||
```
|
||||
|
||||
If the file doesn't exist, run `uv lock` and commit it to your repository:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
### 3. Validate CrewBase Decorator Usage
|
||||
|
||||
**Every crew class must use the `@CrewBase` decorator.** This applies to:
|
||||
|
||||
- Standalone crew projects
|
||||
- Crews embedded inside Flow projects
|
||||
|
||||
```python
|
||||
from crewai import Agent, Crew, Process, Task
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from typing import List
|
||||
|
||||
@CrewBase # This decorator is REQUIRED
|
||||
class MyCrew():
|
||||
"""My crew description"""
|
||||
|
||||
agents: List[BaseAgent]
|
||||
tasks: List[Task]
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
@task
|
||||
def my_task(self) -> Task:
|
||||
return Task(
|
||||
config=self.tasks_config['my_task'] # type: ignore[index]
|
||||
)
|
||||
|
||||
@crew
|
||||
def crew(self) -> Crew:
|
||||
return Crew(
|
||||
agents=self.agents,
|
||||
tasks=self.tasks,
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
)
|
||||
```
|
||||
|
||||
<Warning>
|
||||
If you forget the `@CrewBase` decorator, your deployment will fail with
|
||||
errors about missing agents or tasks configurations.
|
||||
</Warning>
|
||||
|
||||
### 4. Check Project Entry Points
|
||||
|
||||
Both Crews and Flows have their entry point in `src/project_name/main.py`:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="For Crews">
|
||||
The entry point uses a `run()` function:
|
||||
|
||||
```python
|
||||
# src/my_crew/main.py
|
||||
from my_crew.crew import MyCrew
|
||||
|
||||
def run():
|
||||
"""Run the crew."""
|
||||
inputs = {'topic': 'AI in Healthcare'}
|
||||
result = MyCrew().crew().kickoff(inputs=inputs)
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="For Flows">
|
||||
The entry point uses a `kickoff()` function with a Flow class:
|
||||
|
||||
```python
|
||||
# src/my_flow/main.py
|
||||
from crewai.flow import Flow, listen, start
|
||||
from my_flow.crews.poem_crew.poem_crew import PoemCrew
|
||||
|
||||
class MyFlow(Flow):
|
||||
@start()
|
||||
def begin(self):
|
||||
# Flow logic here
|
||||
result = PoemCrew().crew().kickoff(inputs={...})
|
||||
return result
|
||||
|
||||
def kickoff():
|
||||
"""Run the flow."""
|
||||
MyFlow().kickoff()
|
||||
|
||||
if __name__ == "__main__":
|
||||
kickoff()
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 5. Prepare Environment Variables
|
||||
|
||||
Before deployment, ensure you have:
|
||||
|
||||
1. **LLM API keys** ready (OpenAI, Anthropic, Google, etc.)
|
||||
2. **Tool API keys** if using external tools (Serper, etc.)
|
||||
|
||||
<Tip>
|
||||
Test your project locally with the same environment variables before deploying
|
||||
to catch configuration issues early.
|
||||
</Tip>
|
||||
|
||||
## Quick Validation Commands
|
||||
|
||||
Run these commands from your project root to quickly verify your setup:
|
||||
|
||||
```bash
|
||||
# 1. Check project type in pyproject.toml
|
||||
grep -A2 "\[tool.crewai\]" pyproject.toml
|
||||
|
||||
# 2. Verify uv.lock exists
|
||||
ls -la uv.lock || echo "ERROR: uv.lock missing! Run 'uv lock'"
|
||||
|
||||
# 3. Verify src/ structure exists
|
||||
ls -la src/*/main.py 2>/dev/null || echo "No main.py found in src/"
|
||||
|
||||
# 4. For Crews - verify crew.py exists
|
||||
ls -la src/*/crew.py 2>/dev/null || echo "No crew.py (expected for Crews)"
|
||||
|
||||
# 5. For Flows - verify crews/ folder exists
|
||||
ls -la src/*/crews/ 2>/dev/null || echo "No crews/ folder (expected for Flows)"
|
||||
|
||||
# 6. Check for CrewBase usage
|
||||
grep -r "@CrewBase" . --include="*.py"
|
||||
```
|
||||
|
||||
## Common Setup Mistakes
|
||||
|
||||
| Mistake | Symptom | Fix |
|
||||
|---------|---------|-----|
|
||||
| Missing `uv.lock` | Build fails during dependency resolution | Run `uv lock` and commit |
|
||||
| Wrong `type` in pyproject.toml | Build succeeds but runtime fails | Change to correct type |
|
||||
| Missing `@CrewBase` decorator | "Config not found" errors | Add decorator to all crew classes |
|
||||
| Files at root instead of `src/` | Entry point not found | Move to `src/project_name/` |
|
||||
| Missing `run()` or `kickoff()` | Cannot start automation | Add correct entry function |
|
||||
|
||||
## Next Steps
|
||||
|
||||
Once your project passes all checklist items, you're ready to deploy:
|
||||
|
||||
<Card title="Deploy to AMP" icon="rocket" href="/en/enterprise/guides/deploy-to-amp">
|
||||
Follow the deployment guide to deploy your Crew or Flow to CrewAI AMP using
|
||||
the CLI, web interface, or CI/CD integration.
|
||||
</Card>
|
||||
@@ -224,6 +224,60 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `groupFields` (string, optional): Fields to include (e.g., 'name,memberCount,clientData'). Default: name,memberCount
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/get_contact_group">
|
||||
**Description:** Get a specific contact group by resource name.
|
||||
|
||||
**Parameters:**
|
||||
- `resourceName` (string, required): The resource name of the contact group (e.g., 'contactGroups/myContactGroup')
|
||||
- `maxMembers` (integer, optional): Maximum number of members to include. Minimum: 0, Maximum: 20000
|
||||
- `groupFields` (string, optional): Fields to include (e.g., 'name,memberCount,clientData'). Default: name,memberCount
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/create_contact_group">
|
||||
**Description:** Create a new contact group (label).
|
||||
|
||||
**Parameters:**
|
||||
- `name` (string, required): The name of the contact group
|
||||
- `clientData` (array, optional): Client-specific data
|
||||
```json
|
||||
[
|
||||
{
|
||||
"key": "data_key",
|
||||
"value": "data_value"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/update_contact_group">
|
||||
**Description:** Update a contact group's information.
|
||||
|
||||
**Parameters:**
|
||||
- `resourceName` (string, required): The resource name of the contact group (e.g., 'contactGroups/myContactGroup')
|
||||
- `name` (string, required): The name of the contact group
|
||||
- `clientData` (array, optional): Client-specific data
|
||||
```json
|
||||
[
|
||||
{
|
||||
"key": "data_key",
|
||||
"value": "data_value"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/delete_contact_group">
|
||||
**Description:** Delete a contact group.
|
||||
|
||||
**Parameters:**
|
||||
- `resourceName` (string, required): The resource name of the contact group to delete (e.g., 'contactGroups/myContactGroup')
|
||||
- `deleteContacts` (boolean, optional): Whether to delete contacts in the group as well. Default: false
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -132,6 +132,297 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `endIndex` (integer, required): The end index of the range.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_document_with_content">
|
||||
**Description:** Create a new Google Document with content in one action.
|
||||
|
||||
**Parameters:**
|
||||
- `title` (string, required): The title for the new document. Appears at the top of the document and in Google Drive.
|
||||
- `content` (string, optional): The text content to insert into the document. Use `\n` for new paragraphs.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/append_text">
|
||||
**Description:** Append text to the end of a Google Document. Automatically inserts at the document end without needing to specify an index.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID from create_document response or URL.
|
||||
- `text` (string, required): Text to append at the end of the document. Use `\n` for new paragraphs.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_bold">
|
||||
**Description:** Make text bold or remove bold formatting in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `bold` (boolean, required): Set `true` to make bold, `false` to remove bold.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_italic">
|
||||
**Description:** Make text italic or remove italic formatting in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `italic` (boolean, required): Set `true` to make italic, `false` to remove italic.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_underline">
|
||||
**Description:** Add or remove underline formatting from text in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `underline` (boolean, required): Set `true` to underline, `false` to remove underline.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_strikethrough">
|
||||
**Description:** Add or remove strikethrough formatting from text in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `strikethrough` (boolean, required): Set `true` to add strikethrough, `false` to remove.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_font_size">
|
||||
**Description:** Change the font size of text in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `fontSize` (number, required): Font size in points. Common sizes: 10, 11, 12, 14, 16, 18, 24, 36.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_color">
|
||||
**Description:** Change the color of text using RGB values (0-1 scale) in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to format.
|
||||
- `endIndex` (integer, required): End position of text to format (exclusive).
|
||||
- `red` (number, required): Red component (0-1). Example: `1` for full red.
|
||||
- `green` (number, required): Green component (0-1). Example: `0.5` for half green.
|
||||
- `blue` (number, required): Blue component (0-1). Example: `0` for no blue.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_hyperlink">
|
||||
**Description:** Turn existing text into a clickable hyperlink in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of text to make into a link.
|
||||
- `endIndex` (integer, required): End position of text to make into a link (exclusive).
|
||||
- `url` (string, required): The URL the link should point to. Example: `"https://example.com"`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/apply_heading_style">
|
||||
**Description:** Apply a heading or paragraph style to a text range in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of paragraph(s) to style.
|
||||
- `endIndex` (integer, required): End position of paragraph(s) to style.
|
||||
- `style` (string, required): The style to apply. Enum: `NORMAL_TEXT`, `TITLE`, `SUBTITLE`, `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_paragraph_alignment">
|
||||
**Description:** Set text alignment for paragraphs in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of paragraph(s) to align.
|
||||
- `endIndex` (integer, required): End position of paragraph(s) to align.
|
||||
- `alignment` (string, required): Text alignment. Enum: `START` (left), `CENTER`, `END` (right), `JUSTIFIED`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_line_spacing">
|
||||
**Description:** Set line spacing for paragraphs in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of paragraph(s).
|
||||
- `endIndex` (integer, required): End position of paragraph(s).
|
||||
- `lineSpacing` (number, required): Line spacing as percentage. `100` = single, `115` = 1.15x, `150` = 1.5x, `200` = double.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_paragraph_bullets">
|
||||
**Description:** Convert paragraphs to a bulleted or numbered list in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of paragraphs to convert to list.
|
||||
- `endIndex` (integer, required): End position of paragraphs to convert to list.
|
||||
- `bulletPreset` (string, required): Bullet/numbering style. Enum: `BULLET_DISC_CIRCLE_SQUARE`, `BULLET_DIAMONDX_ARROW3D_SQUARE`, `BULLET_CHECKBOX`, `BULLET_ARROW_DIAMOND_DISC`, `BULLET_STAR_CIRCLE_SQUARE`, `NUMBERED_DECIMAL_ALPHA_ROMAN`, `NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS`, `NUMBERED_DECIMAL_NESTED`, `NUMBERED_UPPERALPHA_ALPHA_ROMAN`, `NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_paragraph_bullets">
|
||||
**Description:** Remove bullets or numbering from paragraphs in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `startIndex` (integer, required): Start position of list paragraphs.
|
||||
- `endIndex` (integer, required): End position of list paragraphs.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_with_content">
|
||||
**Description:** Insert a table with content into a Google Document in one action. Provide content as a 2D array.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `rows` (integer, required): Number of rows in the table.
|
||||
- `columns` (integer, required): Number of columns in the table.
|
||||
- `index` (integer, optional): Position to insert the table. If not provided, the table is inserted at the end of the document.
|
||||
- `content` (array, required): Table content as a 2D array. Each inner array is a row. Example: `[["Year", "Revenue"], ["2023", "$43B"], ["2024", "$45B"]]`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_row">
|
||||
**Description:** Insert a new row above or below a reference cell in an existing table.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table. Get from get_document.
|
||||
- `rowIndex` (integer, required): Row index (0-based) of reference cell.
|
||||
- `columnIndex` (integer, optional): Column index (0-based) of reference cell. Default is `0`.
|
||||
- `insertBelow` (boolean, optional): If `true`, insert below the reference row. If `false`, insert above. Default is `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_column">
|
||||
**Description:** Insert a new column left or right of a reference cell in an existing table.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table.
|
||||
- `rowIndex` (integer, optional): Row index (0-based) of reference cell. Default is `0`.
|
||||
- `columnIndex` (integer, required): Column index (0-based) of reference cell.
|
||||
- `insertRight` (boolean, optional): If `true`, insert to the right. If `false`, insert to the left. Default is `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_row">
|
||||
**Description:** Delete a row from an existing table in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table.
|
||||
- `rowIndex` (integer, required): Row index (0-based) to delete.
|
||||
- `columnIndex` (integer, optional): Column index (0-based) of any cell in the row. Default is `0`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_column">
|
||||
**Description:** Delete a column from an existing table in a Google Document.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table.
|
||||
- `rowIndex` (integer, optional): Row index (0-based) of any cell in the column. Default is `0`.
|
||||
- `columnIndex` (integer, required): Column index (0-based) to delete.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/merge_table_cells">
|
||||
**Description:** Merge a range of table cells into a single cell. Content from all cells is preserved.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table.
|
||||
- `rowIndex` (integer, required): Starting row index (0-based) for the merge.
|
||||
- `columnIndex` (integer, required): Starting column index (0-based) for the merge.
|
||||
- `rowSpan` (integer, required): Number of rows to merge.
|
||||
- `columnSpan` (integer, required): Number of columns to merge.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/unmerge_table_cells">
|
||||
**Description:** Unmerge previously merged table cells back into individual cells.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `tableStartIndex` (integer, required): The start index of the table.
|
||||
- `rowIndex` (integer, required): Row index (0-based) of the merged cell.
|
||||
- `columnIndex` (integer, required): Column index (0-based) of the merged cell.
|
||||
- `rowSpan` (integer, required): Number of rows the merged cell spans.
|
||||
- `columnSpan` (integer, required): Number of columns the merged cell spans.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_inline_image">
|
||||
**Description:** Insert an image from a public URL into a Google Document. The image must be publicly accessible, under 50MB, and in PNG/JPEG/GIF format.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `uri` (string, required): Public URL of the image. Must be accessible without authentication.
|
||||
- `index` (integer, optional): Position to insert the image. If not provided, the image is inserted at the end of the document. Default is `1`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_section_break">
|
||||
**Description:** Insert a section break to create document sections with different formatting.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `index` (integer, required): Position to insert the section break.
|
||||
- `sectionType` (string, required): The type of section break. Enum: `CONTINUOUS` (stays on same page), `NEXT_PAGE` (starts a new page).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_header">
|
||||
**Description:** Create a header for the document. Returns a headerId which can be used with insert_text to add header content.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `type` (string, optional): Header type. Enum: `DEFAULT`. Default is `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_footer">
|
||||
**Description:** Create a footer for the document. Returns a footerId which can be used with insert_text to add footer content.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `type` (string, optional): Footer type. Enum: `DEFAULT`. Default is `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_header">
|
||||
**Description:** Delete a header from the document. Use get_document to find the headerId.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `headerId` (string, required): The header ID to delete. Get from get_document response.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_footer">
|
||||
**Description:** Delete a footer from the document. Use get_document to find the footerId.
|
||||
|
||||
**Parameters:**
|
||||
- `documentId` (string, required): The document ID.
|
||||
- `footerId` (string, required): The footer ID to delete. Get from get_document response.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -62,6 +62,22 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_metadata">
|
||||
**Description:** Get lightweight metadata about a presentation (title, slide count, slide IDs). Use this first before fetching full content.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation to retrieve.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_text">
|
||||
**Description:** Extract all text content from a presentation. Returns slide IDs and text from shapes and tables only (no formatting).
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation">
|
||||
**Description:** Retrieves a presentation by ID.
|
||||
|
||||
@@ -96,6 +112,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_slide_text">
|
||||
**Description:** Extract text content from a single slide. Returns only text from shapes and tables (no formatting or styling).
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `pageObjectId` (string, required): The ID of the slide/page to get text from.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_page">
|
||||
**Description:** Retrieves a specific page by its ID.
|
||||
|
||||
@@ -114,6 +139,120 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide">
|
||||
**Description:** Add an additional blank slide to a presentation. New presentations already have one blank slide - check get_presentation_metadata first. For slides with title/body areas, use create_slide_with_layout instead.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `insertionIndex` (integer, optional): Where to insert the slide (0-based). If omitted, adds at the end.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide_with_layout">
|
||||
**Description:** Create a slide with a predefined layout containing placeholder areas for title, body, etc. This is better than create_slide for structured content. After creating, use get_page to find placeholder IDs, then insert text into them.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `layout` (string, required): Layout type. One of: `BLANK`, `TITLE`, `TITLE_AND_BODY`, `TITLE_AND_TWO_COLUMNS`, `TITLE_ONLY`, `SECTION_HEADER`, `ONE_COLUMN_TEXT`, `MAIN_POINT`, `BIG_NUMBER`. TITLE_AND_BODY is best for title+description. TITLE for title-only slides. SECTION_HEADER for section dividers.
|
||||
- `insertionIndex` (integer, optional): Where to insert (0-based). Omit to add at end.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_text_box">
|
||||
**Description:** Create a text box on a slide with content. Use this for titles, descriptions, paragraphs - not tables. Optionally specify position (x, y) and size (width, height) in EMU units (914400 EMU = 1 inch).
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to add the text box to.
|
||||
- `text` (string, required): The text content for the text box.
|
||||
- `x` (integer, optional): X position in EMU (914400 = 1 inch). Default: 914400 (1 inch from left).
|
||||
- `y` (integer, optional): Y position in EMU (914400 = 1 inch). Default: 914400 (1 inch from top).
|
||||
- `width` (integer, optional): Width in EMU. Default: 7315200 (~8 inches).
|
||||
- `height` (integer, optional): Height in EMU. Default: 914400 (~1 inch).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/delete_slide">
|
||||
**Description:** Remove a slide from the presentation. Use get_presentation first to find the slide ID.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The object ID of the slide to delete. Get from get_presentation.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/duplicate_slide">
|
||||
**Description:** Create a copy of an existing slide. The duplicate is inserted immediately after the original.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The object ID of the slide to duplicate. Get from get_presentation.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/move_slides">
|
||||
**Description:** Reorder slides by moving them to a new position. Slide IDs must be in their current presentation order (no duplicates).
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideIds` (array of strings, required): Array of slide IDs to move. Must be in current presentation order.
|
||||
- `insertionIndex` (integer, required): Target position (0-based). 0 = beginning, slide count = end.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_youtube_video">
|
||||
**Description:** Embed a YouTube video on a slide. The video ID is the value after "v=" in YouTube URLs (e.g., for youtube.com/watch?v=abc123, use "abc123").
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to add the video to. Get from get_presentation.
|
||||
- `videoId` (string, required): The YouTube video ID (the value after v= in the URL).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_drive_video">
|
||||
**Description:** Embed a video from Google Drive on a slide. The file ID can be found in the Drive file URL.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to add the video to. Get from get_presentation.
|
||||
- `fileId` (string, required): The Google Drive file ID of the video.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/set_slide_background_image">
|
||||
**Description:** Set a background image for a slide. The image URL must be publicly accessible.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to set the background for. Get from get_presentation.
|
||||
- `imageUrl` (string, required): Publicly accessible URL of the image to use as background.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table">
|
||||
**Description:** Create an empty table on a slide. To create a table with content, use create_table_with_content instead.
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to add the table to. Get from get_presentation.
|
||||
- `rows` (integer, required): Number of rows in the table.
|
||||
- `columns` (integer, required): Number of columns in the table.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table_with_content">
|
||||
**Description:** Create a table with content in one action. Provide content as a 2D array where each inner array is a row. Example: [["Header1", "Header2"], ["Row1Col1", "Row1Col2"]].
|
||||
|
||||
**Parameters:**
|
||||
- `presentationId` (string, required): The ID of the presentation.
|
||||
- `slideId` (string, required): The ID of the slide to add the table to. Get from get_presentation.
|
||||
- `rows` (integer, required): Number of rows in the table.
|
||||
- `columns` (integer, required): Number of columns in the table.
|
||||
- `content` (array, required): Table content as 2D array. Each inner array is a row. Example: [["Year", "Revenue"], ["2023", "$10M"]].
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/import_data_from_sheet">
|
||||
**Description:** Imports data from a Google Sheet into a presentation.
|
||||
|
||||
|
||||
@@ -169,6 +169,16 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_table_data">
|
||||
**Description:** Get data from a specific table in an Excel worksheet.
|
||||
|
||||
**Parameters:**
|
||||
- `file_id` (string, required): The ID of the Excel file
|
||||
- `worksheet_name` (string, required): Name of the worksheet
|
||||
- `table_name` (string, required): Name of the table
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/create_chart">
|
||||
**Description:** Create a chart in an Excel worksheet.
|
||||
|
||||
@@ -201,6 +211,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_used_range_metadata">
|
||||
**Description:** Get the used range metadata (dimensions only, no data) of an Excel worksheet.
|
||||
|
||||
**Parameters:**
|
||||
- `file_id` (string, required): The ID of the Excel file
|
||||
- `worksheet_name` (string, required): Name of the worksheet
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/list_charts">
|
||||
**Description:** Get all charts in an Excel worksheet.
|
||||
|
||||
|
||||
@@ -151,6 +151,49 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `item_id` (string, required): The ID of the file.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/list_files_by_path">
|
||||
**Description:** List files and folders in a specific OneDrive path.
|
||||
|
||||
**Parameters:**
|
||||
- `folder_path` (string, required): The folder path (e.g., 'Documents/Reports').
|
||||
- `top` (integer, optional): Number of items to retrieve (max 1000). Default is `50`.
|
||||
- `orderby` (string, optional): Order by field (e.g., "name asc", "lastModifiedDateTime desc"). Default is "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_recent_files">
|
||||
**Description:** Get recently accessed files from OneDrive.
|
||||
|
||||
**Parameters:**
|
||||
- `top` (integer, optional): Number of items to retrieve (max 200). Default is `25`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_shared_with_me">
|
||||
**Description:** Get files and folders shared with the user.
|
||||
|
||||
**Parameters:**
|
||||
- `top` (integer, optional): Number of items to retrieve (max 200). Default is `50`.
|
||||
- `orderby` (string, optional): Order by field. Default is "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_file_by_path">
|
||||
**Description:** Get information about a specific file or folder by path.
|
||||
|
||||
**Parameters:**
|
||||
- `file_path` (string, required): The file or folder path (e.g., 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/download_file_by_path">
|
||||
**Description:** Download a file from OneDrive by its path.
|
||||
|
||||
**Parameters:**
|
||||
- `file_path` (string, required): The file path (e.g., 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -133,6 +133,74 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `companyName` (string, optional): Contact's company name.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/get_message">
|
||||
**Description:** Get a specific email message by ID.
|
||||
|
||||
**Parameters:**
|
||||
- `message_id` (string, required): The unique identifier of the message. Obtain from get_messages action.
|
||||
- `select` (string, optional): Comma-separated list of properties to return. Example: "id,subject,body,from,receivedDateTime". Default is "id,subject,body,from,toRecipients,receivedDateTime".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/reply_to_email">
|
||||
**Description:** Reply to an email message.
|
||||
|
||||
**Parameters:**
|
||||
- `message_id` (string, required): The unique identifier of the message to reply to. Obtain from get_messages action.
|
||||
- `comment` (string, required): The reply message content. Can be plain text or HTML. The original message will be quoted below this content.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/forward_email">
|
||||
**Description:** Forward an email message.
|
||||
|
||||
**Parameters:**
|
||||
- `message_id` (string, required): The unique identifier of the message to forward. Obtain from get_messages action.
|
||||
- `to_recipients` (array, required): Array of recipient email addresses to forward to. Example: ["john@example.com", "jane@example.com"].
|
||||
- `comment` (string, optional): Optional message to include above the forwarded content. Can be plain text or HTML.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/mark_message_read">
|
||||
**Description:** Mark a message as read or unread.
|
||||
|
||||
**Parameters:**
|
||||
- `message_id` (string, required): The unique identifier of the message. Obtain from get_messages action.
|
||||
- `is_read` (boolean, required): Set to true to mark as read, false to mark as unread.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_message">
|
||||
**Description:** Delete an email message.
|
||||
|
||||
**Parameters:**
|
||||
- `message_id` (string, required): The unique identifier of the message to delete. Obtain from get_messages action.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/update_event">
|
||||
**Description:** Update an existing calendar event.
|
||||
|
||||
**Parameters:**
|
||||
- `event_id` (string, required): The unique identifier of the event. Obtain from get_calendar_events action.
|
||||
- `subject` (string, optional): New subject/title for the event.
|
||||
- `start_time` (string, optional): New start time in ISO 8601 format (e.g., "2024-01-20T10:00:00"). REQUIRED: Must also provide start_timezone when using this field.
|
||||
- `start_timezone` (string, optional): Timezone for start time. REQUIRED when updating start_time. Examples: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `end_time` (string, optional): New end time in ISO 8601 format. REQUIRED: Must also provide end_timezone when using this field.
|
||||
- `end_timezone` (string, optional): Timezone for end time. REQUIRED when updating end_time. Examples: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `location` (string, optional): New location for the event.
|
||||
- `body` (string, optional): New body/description for the event. Supports HTML formatting.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_event">
|
||||
**Description:** Delete a calendar event.
|
||||
|
||||
**Parameters:**
|
||||
- `event_id` (string, required): The unique identifier of the event to delete. Obtain from get_calendar_events action.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -78,6 +78,17 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drives">
|
||||
**Description:** List all document libraries (drives) in a SharePoint site. Use this to discover available libraries before using file operations.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `top` (integer, optional): Maximum number of drives to return per page (1-999). Default is 100
|
||||
- `skip_token` (string, optional): Pagination token from a previous response to fetch the next page of results
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'id,name,webUrl,driveType')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_site_lists">
|
||||
**Description:** Get all lists in a SharePoint site.
|
||||
|
||||
@@ -159,20 +170,317 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drive_items">
|
||||
**Description:** Get files and folders from a SharePoint document library.
|
||||
<Accordion title="microsoft_sharepoint/list_files">
|
||||
**Description:** Retrieve files and folders from a SharePoint document library. By default lists the root folder, but you can navigate into subfolders by providing a folder_id.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The ID of the SharePoint site
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `folder_id` (string, optional): The ID of the folder to list contents from. Use 'root' for the root folder, or provide a folder ID from a previous list_files call. Default is 'root'
|
||||
- `top` (integer, optional): Maximum number of items to return per page (1-1000). Default is 50
|
||||
- `skip_token` (string, optional): Pagination token from a previous response to fetch the next page of results
|
||||
- `orderby` (string, optional): Sort order for results (e.g., 'name asc', 'size desc', 'lastModifiedDateTime desc'). Default is 'name asc'
|
||||
- `filter` (string, optional): OData filter to narrow results (e.g., 'file ne null' for files only, 'folder ne null' for folders only)
|
||||
- `select` (string, optional): Comma-separated list of fields to return (e.g., 'id,name,size,folder,file,webUrl,lastModifiedDateTime')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_drive_item">
|
||||
**Description:** Delete a file or folder from SharePoint document library.
|
||||
<Accordion title="microsoft_sharepoint/delete_file">
|
||||
**Description:** Delete a file or folder from a SharePoint document library. For folders, all contents are deleted recursively. Items are moved to the site recycle bin.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The ID of the SharePoint site
|
||||
- `item_id` (string, required): The ID of the file or folder to delete
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the file or folder to delete. Obtain from list_files
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_files_by_path">
|
||||
**Description:** List files and folders in a SharePoint document library folder by its path. More efficient than multiple list_files calls for deep navigation.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `folder_path` (string, required): The full path to the folder without leading/trailing slashes (e.g., 'Documents', 'Reports/2024/Q1')
|
||||
- `top` (integer, optional): Maximum number of items to return per page (1-1000). Default is 50
|
||||
- `skip_token` (string, optional): Pagination token from a previous response to fetch the next page of results
|
||||
- `orderby` (string, optional): Sort order for results (e.g., 'name asc', 'size desc'). Default is 'name asc'
|
||||
- `select` (string, optional): Comma-separated list of fields to return (e.g., 'id,name,size,folder,file,webUrl,lastModifiedDateTime')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/download_file">
|
||||
**Description:** Download raw file content from a SharePoint document library. Use only for plain text files (.txt, .csv, .json). For Excel files, use the Excel-specific actions. For Word files, use get_word_document_content.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the file to download. Obtain from list_files or list_files_by_path
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_file_info">
|
||||
**Description:** Retrieve detailed metadata for a specific file or folder in a SharePoint document library, including name, size, created/modified dates, and author information.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the file or folder. Obtain from list_files or list_files_by_path
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'id,name,size,createdDateTime,lastModifiedDateTime,webUrl,createdBy,lastModifiedBy')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_folder">
|
||||
**Description:** Create a new folder in a SharePoint document library. By default creates the folder in the root; use parent_id to create subfolders.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `folder_name` (string, required): Name for the new folder. Cannot contain: \ / : * ? " < > |
|
||||
- `parent_id` (string, optional): The ID of the parent folder. Use 'root' for the document library root, or provide a folder ID from list_files. Default is 'root'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/search_files">
|
||||
**Description:** Search for files and folders in a SharePoint document library by keywords. Searches file names, folder names, and file contents for Office documents. Do not use wildcards or special characters.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `query` (string, required): Search keywords (e.g., 'report', 'budget 2024'). Wildcards like *.txt are not supported
|
||||
- `top` (integer, optional): Maximum number of results to return per page (1-1000). Default is 50
|
||||
- `skip_token` (string, optional): Pagination token from a previous response to fetch the next page of results
|
||||
- `select` (string, optional): Comma-separated list of fields to return (e.g., 'id,name,size,folder,file,webUrl,lastModifiedDateTime')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/copy_file">
|
||||
**Description:** Copy a file or folder to a new location within SharePoint. The original item remains unchanged. The copy operation is asynchronous for large files.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the file or folder to copy. Obtain from list_files or search_files
|
||||
- `destination_folder_id` (string, required): The ID of the destination folder. Use 'root' for the root folder, or a folder ID from list_files
|
||||
- `new_name` (string, optional): New name for the copy. If not provided, the original name is used
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/move_file">
|
||||
**Description:** Move a file or folder to a new location within SharePoint. The item is removed from its original location. For folders, all contents are moved as well.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the file or folder to move. Obtain from list_files or search_files
|
||||
- `destination_folder_id` (string, required): The ID of the destination folder. Use 'root' for the root folder, or a folder ID from list_files
|
||||
- `new_name` (string, optional): New name for the moved item. If not provided, the original name is kept
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_worksheets">
|
||||
**Description:** List all worksheets (tabs) in an Excel workbook stored in a SharePoint document library. Use the returned worksheet name with other Excel actions.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'id,name,position,visibility')
|
||||
- `filter` (string, optional): OData filter expression (e.g., "visibility eq 'Visible'" to exclude hidden sheets)
|
||||
- `top` (integer, optional): Maximum number of worksheets to return. Minimum: 1, Maximum: 999
|
||||
- `orderby` (string, optional): Sort order (e.g., 'position asc' to return sheets in tab order)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_worksheet">
|
||||
**Description:** Create a new worksheet (tab) in an Excel workbook stored in a SharePoint document library. The new sheet is added at the end of the tab list.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `name` (string, required): Name for the new worksheet. Maximum 31 characters. Cannot contain: \ / * ? : [ ]. Must be unique within the workbook
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_range_data">
|
||||
**Description:** Retrieve cell values from a specific range in an Excel worksheet stored in SharePoint. For reading all data without knowing dimensions, use get_excel_used_range instead.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet (tab) to read from. Obtain from get_excel_worksheets. Case-sensitive
|
||||
- `range` (string, required): Cell range in A1 notation (e.g., 'A1:C10', 'A:C', '1:5', 'A1')
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'address,values,formulas,numberFormat,text')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/update_excel_range_data">
|
||||
**Description:** Write values to a specific range in an Excel worksheet stored in SharePoint. Overwrites existing cell contents. The values array dimensions must match the range dimensions exactly.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet (tab) to update. Obtain from get_excel_worksheets. Case-sensitive
|
||||
- `range` (string, required): Cell range in A1 notation where values will be written (e.g., 'A1:C3' for a 3x3 block)
|
||||
- `values` (array, required): 2D array of values (rows containing cells). Example for A1:B2: [["Header1", "Header2"], ["Value1", "Value2"]]. Use null to clear a cell
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range_metadata">
|
||||
**Description:** Return only the metadata (address and dimensions) of the used range in a worksheet, without the actual cell values. Ideal for large files to understand spreadsheet size before reading data in chunks.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet (tab) to read. Obtain from get_excel_worksheets. Case-sensitive
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range">
|
||||
**Description:** Retrieve all cells containing data in a worksheet stored in SharePoint. Do not use for files larger than 2MB. For large files, use get_excel_used_range_metadata first, then get_excel_range_data to read in smaller chunks.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet (tab) to read. Obtain from get_excel_worksheets. Case-sensitive
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'address,values,formulas,numberFormat,text,rowCount,columnCount')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_cell">
|
||||
**Description:** Retrieve the value of a single cell by row and column index from an Excel file in SharePoint. Indices are 0-based (row 0 = Excel row 1, column 0 = column A).
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet (tab). Obtain from get_excel_worksheets. Case-sensitive
|
||||
- `row` (integer, required): 0-based row index (row 0 = Excel row 1). Valid range: 0-1048575
|
||||
- `column` (integer, required): 0-based column index (column 0 = A, column 1 = B). Valid range: 0-16383
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'address,values,formulas,numberFormat,text')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table">
|
||||
**Description:** Convert a cell range into a formatted Excel table with filtering, sorting, and structured data capabilities. Tables enable add_excel_table_row for appending data.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet containing the data range. Obtain from get_excel_worksheets
|
||||
- `range` (string, required): Cell range to convert into a table, including headers and data (e.g., 'A1:D10' where A1:D1 contains column headers)
|
||||
- `has_headers` (boolean, optional): Set to true if the first row contains column headers. Default is true
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_tables">
|
||||
**Description:** List all tables in a specific Excel worksheet stored in SharePoint. Returns table properties including id, name, showHeaders, and showTotals.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet to get tables from. Obtain from get_excel_worksheets
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table_row">
|
||||
**Description:** Append a new row to the end of an Excel table in a SharePoint file. The values array must have the same number of elements as the table has columns.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet containing the table. Obtain from get_excel_worksheets
|
||||
- `table_name` (string, required): Name of the table to add the row to (e.g., 'Table1'). Obtain from get_excel_tables. Case-sensitive
|
||||
- `values` (array, required): Array of cell values for the new row, one per column in table order (e.g., ["John Doe", "john@example.com", 25])
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_table_data">
|
||||
**Description:** Get all rows from an Excel table in a SharePoint file as a data range. Easier than get_excel_range_data when working with structured tables since you don't need to know the exact range.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet containing the table. Obtain from get_excel_worksheets
|
||||
- `table_name` (string, required): Name of the table to get data from (e.g., 'Table1'). Obtain from get_excel_tables. Case-sensitive
|
||||
- `select` (string, optional): Comma-separated list of properties to return (e.g., 'address,values,formulas,numberFormat,text')
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_chart">
|
||||
**Description:** Create a chart visualization in an Excel worksheet stored in SharePoint from a data range. The chart is embedded in the worksheet.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet where the chart will be created. Obtain from get_excel_worksheets
|
||||
- `chart_type` (string, required): Chart type (e.g., 'ColumnClustered', 'ColumnStacked', 'Line', 'LineMarkers', 'Pie', 'Bar', 'BarClustered', 'Area', 'Scatter', 'Doughnut')
|
||||
- `source_data` (string, required): Data range for the chart in A1 notation, including headers (e.g., 'A1:B10')
|
||||
- `series_by` (string, optional): How data series are organized: 'Auto', 'Columns', or 'Rows'. Default is 'Auto'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_charts">
|
||||
**Description:** List all charts embedded in an Excel worksheet stored in SharePoint. Returns chart properties including id, name, chartType, height, width, and position.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet to list charts from. Obtain from get_excel_worksheets
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_worksheet">
|
||||
**Description:** Permanently remove a worksheet (tab) and all its contents from an Excel workbook stored in SharePoint. Cannot be undone. A workbook must have at least one worksheet.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet to delete. Case-sensitive. All data, tables, and charts on this sheet will be permanently removed
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_table">
|
||||
**Description:** Remove a table from an Excel worksheet in SharePoint. This deletes the table structure (filtering, formatting, table features) but preserves the underlying cell data.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
- `worksheet_name` (string, required): Name of the worksheet containing the table. Obtain from get_excel_worksheets
|
||||
- `table_name` (string, required): Name of the table to delete (e.g., 'Table1'). Obtain from get_excel_tables. The data in the cells will remain after table deletion
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_names">
|
||||
**Description:** Retrieve all named ranges defined in an Excel workbook stored in SharePoint. Named ranges are user-defined labels for cell ranges (e.g., 'SalesData' for A1:D100).
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Excel file in SharePoint. Obtain from list_files or search_files
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_word_document_content">
|
||||
**Description:** Download and extract text content from a Word document (.docx) stored in a SharePoint document library. This is the recommended way to read Word documents from SharePoint.
|
||||
|
||||
**Parameters:**
|
||||
- `site_id` (string, required): The full SharePoint site identifier from get_sites
|
||||
- `drive_id` (string, required): The ID of the document library. Call get_drives first to get valid drive IDs
|
||||
- `item_id` (string, required): The unique identifier of the Word document (.docx) in SharePoint. Obtain from list_files or search_files
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -108,6 +108,86 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `join_web_url` (string, required): The join web URL of the meeting to search for.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/search_online_meetings_by_meeting_id">
|
||||
**Description:** Search online meetings by external Meeting ID.
|
||||
|
||||
**Parameters:**
|
||||
- `join_meeting_id` (string, required): The meeting ID (numeric code) that attendees use to join. This is the joinMeetingId shown in meeting invitations, not the Graph API meeting id.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_meeting">
|
||||
**Description:** Get details of a specific online meeting.
|
||||
|
||||
**Parameters:**
|
||||
- `meeting_id` (string, required): The Graph API meeting ID (a long alphanumeric string). Obtain from create_meeting or search_online_meetings actions. Different from the numeric joinMeetingId.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_team_members">
|
||||
**Description:** Get members of a specific team.
|
||||
|
||||
**Parameters:**
|
||||
- `team_id` (string, required): The unique identifier of the team. Obtain from get_teams action.
|
||||
- `top` (integer, optional): Maximum number of members to retrieve per page (1-999). Default is `100`.
|
||||
- `skip_token` (string, optional): Pagination token from a previous response. When the response includes @odata.nextLink, extract the $skiptoken parameter value and pass it here to get the next page of results.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/create_channel">
|
||||
**Description:** Create a new channel in a team.
|
||||
|
||||
**Parameters:**
|
||||
- `team_id` (string, required): The unique identifier of the team. Obtain from get_teams action.
|
||||
- `display_name` (string, required): Name of the channel as displayed in Teams. Must be unique within the team. Max 50 characters.
|
||||
- `description` (string, optional): Optional description explaining the channel's purpose. Visible in channel details. Max 1024 characters.
|
||||
- `membership_type` (string, optional): Channel visibility. Enum: `standard`, `private`. "standard" = visible to all team members, "private" = visible only to specifically added members. Default is `standard`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_message_replies">
|
||||
**Description:** Get replies to a specific message in a channel.
|
||||
|
||||
**Parameters:**
|
||||
- `team_id` (string, required): The unique identifier of the team. Obtain from get_teams action.
|
||||
- `channel_id` (string, required): The unique identifier of the channel. Obtain from get_channels action.
|
||||
- `message_id` (string, required): The unique identifier of the parent message. Obtain from get_messages action.
|
||||
- `top` (integer, optional): Maximum number of replies to retrieve per page (1-50). Default is `50`.
|
||||
- `skip_token` (string, optional): Pagination token from a previous response. When the response includes @odata.nextLink, extract the $skiptoken parameter value and pass it here to get the next page of results.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/reply_to_message">
|
||||
**Description:** Reply to a message in a Teams channel.
|
||||
|
||||
**Parameters:**
|
||||
- `team_id` (string, required): The unique identifier of the team. Obtain from get_teams action.
|
||||
- `channel_id` (string, required): The unique identifier of the channel. Obtain from get_channels action.
|
||||
- `message_id` (string, required): The unique identifier of the message to reply to. Obtain from get_messages action.
|
||||
- `message` (string, required): The reply content. For HTML, include formatting tags. For text, plain text only.
|
||||
- `content_type` (string, optional): Content format. Enum: `html`, `text`. "text" for plain text, "html" for rich text with formatting. Default is `text`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/update_meeting">
|
||||
**Description:** Update an existing online meeting.
|
||||
|
||||
**Parameters:**
|
||||
- `meeting_id` (string, required): The unique identifier of the meeting. Obtain from create_meeting or search_online_meetings actions.
|
||||
- `subject` (string, optional): New meeting title.
|
||||
- `startDateTime` (string, optional): New start time in ISO 8601 format with timezone. Example: "2024-01-20T10:00:00-08:00".
|
||||
- `endDateTime` (string, optional): New end time in ISO 8601 format with timezone.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/delete_meeting">
|
||||
**Description:** Delete an online meeting.
|
||||
|
||||
**Parameters:**
|
||||
- `meeting_id` (string, required): The unique identifier of the meeting to delete. Obtain from create_meeting or search_online_meetings actions.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
@@ -98,6 +98,26 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `file_id` (string, required): The ID of the document to delete.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/copy_document">
|
||||
**Description:** Copy a document to a new location in OneDrive.
|
||||
|
||||
**Parameters:**
|
||||
- `file_id` (string, required): The ID of the document to copy
|
||||
- `name` (string, optional): New name for the copied document
|
||||
- `parent_id` (string, optional): The ID of the destination folder (defaults to root)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/move_document">
|
||||
**Description:** Move a document to a new location in OneDrive.
|
||||
|
||||
**Parameters:**
|
||||
- `file_id` (string, required): The ID of the document to move
|
||||
- `parent_id` (string, required): The ID of the destination folder
|
||||
- `name` (string, optional): New name for the moved document
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Usage Examples
|
||||
|
||||
61
docs/en/guides/coding-tools/agents-md.mdx
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Coding Tools
|
||||
description: Use AGENTS.md to guide coding agents and IDEs across your CrewAI projects.
|
||||
icon: terminal
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Why AGENTS.md
|
||||
|
||||
`AGENTS.md` is a lightweight, repo-local instruction file that gives coding agents consistent, project-specific guidance. Keep it in the project root and treat it as the source of truth for how you want assistants to work: conventions, commands, architecture notes, and guardrails.
|
||||
|
||||
## Create a Project with the CLI
|
||||
|
||||
Use the CrewAI CLI to scaffold a project, then `AGENTS.md` will be automatically added at the root.
|
||||
|
||||
```bash
|
||||
# Crew
|
||||
crewai create crew my_crew
|
||||
|
||||
# Flow
|
||||
crewai create flow my_flow
|
||||
|
||||
# Tool repository
|
||||
crewai tool create my_tool
|
||||
```
|
||||
|
||||
## Tool Setup: Point Assistants to AGENTS.md
|
||||
|
||||
### Codex
|
||||
|
||||
Codex can be guided by `AGENTS.md` files placed in your repository. Use them to supply persistent project context such as conventions, commands, and workflow expectations.
|
||||
|
||||
### Claude Code
|
||||
|
||||
Claude Code stores project memory in `CLAUDE.md`. You can bootstrap it with `/init` and edit it using `/memory`. Claude Code also supports imports inside `CLAUDE.md`, so you can add a single line like `@AGENTS.md` to pull in the shared instructions without duplicating them.
|
||||
|
||||
You can simply use:
|
||||
|
||||
```bash
|
||||
mv AGENTS.md CLAUDE.md
|
||||
```
|
||||
|
||||
### Gemini CLI and Google Antigravity
|
||||
|
||||
Gemini CLI and Antigravity load a project context file (default: `GEMINI.md`) from the repo root and parent directories. You can configure it to read `AGENTS.md` instead (or in addition) by setting `context.fileName` in your Gemini CLI settings. For example, set it to `AGENTS.md` only, or include both `AGENTS.md` and `GEMINI.md` if you want to keep each tool’s format.
|
||||
|
||||
You can simply use:
|
||||
|
||||
```bash
|
||||
mv AGENTS.md GEMINI.md
|
||||
```
|
||||
|
||||
### Cursor
|
||||
|
||||
Cursor supports `AGENTS.md` as a project instruction file. Place it at the project root to provide guidance for Cursor’s coding assistant.
|
||||
|
||||
### Windsurf
|
||||
|
||||
Claude Code provides an official integration with Windsurf. If you use Claude Code inside Windsurf, follow the Claude Code guidance above and import `AGENTS.md` from `CLAUDE.md`.
|
||||
|
||||
If you are using Windsurf’s native assistant, configure its project rules or instructions feature (if available) to read from `AGENTS.md` or paste the contents directly.
|
||||
@@ -1,43 +1,48 @@
|
||||
---
|
||||
title: Agent-to-Agent (A2A) Protocol
|
||||
description: Enable CrewAI agents to delegate tasks to remote A2A-compliant agents for specialized handling
|
||||
description: Agents delegate tasks to remote A2A agents and/or operate as A2A-compliant server agents.
|
||||
icon: network-wired
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## A2A Agent Delegation
|
||||
|
||||
CrewAI supports the Agent-to-Agent (A2A) protocol, allowing agents to delegate tasks to remote specialized agents. The agent's LLM automatically decides whether to handle a task directly or delegate to an A2A agent based on the task requirements.
|
||||
|
||||
<Note>
|
||||
A2A delegation requires the `a2a-sdk` package. Install with: `uv add 'crewai[a2a]'` or `pip install 'crewai[a2a]'`
|
||||
</Note>
|
||||
CrewAI treats [A2A protocol](https://a2a-protocol.org/latest/) as a first-class delegation primitive, enabling agents to delegate tasks, request information, and collaborate with remote agents, as well as act as A2A-compliant server agents.
|
||||
In client mode, agents autonomously choose between local execution and remote delegation based on task requirements.
|
||||
|
||||
## How It Works
|
||||
|
||||
When an agent is configured with A2A capabilities:
|
||||
|
||||
1. The LLM analyzes each task
|
||||
1. The Agent analyzes each task
|
||||
2. It decides to either:
|
||||
- Handle the task directly using its own capabilities
|
||||
- Delegate to a remote A2A agent for specialized handling
|
||||
3. If delegating, the agent communicates with the remote A2A agent through the protocol
|
||||
4. Results are returned to the CrewAI workflow
|
||||
|
||||
<Note>
|
||||
A2A delegation requires the `a2a-sdk` package. Install with: `uv add 'crewai[a2a]'` or `pip install 'crewai[a2a]'`
|
||||
</Note>
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
<Warning>
|
||||
`crewai.a2a.config.A2AConfig` is deprecated and will be removed in v2.0.0. Use `A2AClientConfig` for connecting to remote agents and/or `A2AServerConfig` for exposing agents as servers.
|
||||
</Warning>
|
||||
|
||||
Configure an agent for A2A delegation by setting the `a2a` parameter:
|
||||
|
||||
```python Code
|
||||
from crewai import Agent, Crew, Task
|
||||
from crewai.a2a import A2AConfig
|
||||
from crewai.a2a import A2AClientConfig
|
||||
|
||||
agent = Agent(
|
||||
role="Research Coordinator",
|
||||
goal="Coordinate research tasks efficiently",
|
||||
backstory="Expert at delegating to specialized research agents",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://example.com/.well-known/agent-card.json",
|
||||
timeout=120,
|
||||
max_turns=10
|
||||
@@ -54,9 +59,9 @@ crew = Crew(agents=[agent], tasks=[task], verbose=True)
|
||||
result = crew.kickoff()
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
## Client Configuration Options
|
||||
|
||||
The `A2AConfig` class accepts the following parameters:
|
||||
The `A2AClientConfig` class accepts the following parameters:
|
||||
|
||||
<ParamField path="endpoint" type="str" required>
|
||||
The A2A agent endpoint URL (typically points to `.well-known/agent-card.json`)
|
||||
@@ -91,14 +96,34 @@ The `A2AConfig` class accepts the following parameters:
|
||||
Update mechanism for receiving task status. Options: `StreamingConfig`, `PollingConfig`, or `PushNotificationConfig`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="transport_protocol" type="Literal['JSONRPC', 'GRPC', 'HTTP+JSON']" default="JSONRPC">
|
||||
Transport protocol for A2A communication. Options: `JSONRPC` (default), `GRPC`, or `HTTP+JSON`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="accepted_output_modes" type="list[str]" default='["application/json"]'>
|
||||
Media types the client can accept in responses.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="supported_transports" type="list[str]" default='["JSONRPC"]'>
|
||||
Ordered list of transport protocols the client supports.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="use_client_preference" type="bool" default="False">
|
||||
Whether to prioritize client transport preferences over server.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="extensions" type="list[str]" default="[]">
|
||||
Extension URIs the client supports.
|
||||
</ParamField>
|
||||
|
||||
## Authentication
|
||||
|
||||
For A2A agents that require authentication, use one of the provided auth schemes:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Bearer Token">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python bearer_token_auth.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.auth import BearerTokenAuth
|
||||
|
||||
agent = Agent(
|
||||
@@ -106,18 +131,18 @@ agent = Agent(
|
||||
goal="Coordinate tasks with secured agents",
|
||||
backstory="Manages secure agent communications",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://secure-agent.example.com/.well-known/agent-card.json",
|
||||
auth=BearerTokenAuth(token="your-bearer-token"),
|
||||
timeout=120
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API Key">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python api_key_auth.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.auth import APIKeyAuth
|
||||
|
||||
agent = Agent(
|
||||
@@ -125,7 +150,7 @@ agent = Agent(
|
||||
goal="Coordinate with API-based agents",
|
||||
backstory="Manages API-authenticated communications",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://api-agent.example.com/.well-known/agent-card.json",
|
||||
auth=APIKeyAuth(
|
||||
api_key="your-api-key",
|
||||
@@ -135,12 +160,12 @@ agent = Agent(
|
||||
timeout=120
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="OAuth2">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python oauth2_auth.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.auth import OAuth2ClientCredentials
|
||||
|
||||
agent = Agent(
|
||||
@@ -148,7 +173,7 @@ agent = Agent(
|
||||
goal="Coordinate with OAuth-secured agents",
|
||||
backstory="Manages OAuth-authenticated communications",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://oauth-agent.example.com/.well-known/agent-card.json",
|
||||
auth=OAuth2ClientCredentials(
|
||||
token_url="https://auth.example.com/oauth/token",
|
||||
@@ -159,12 +184,12 @@ agent = Agent(
|
||||
timeout=120
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="HTTP Basic">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python http_basic_auth.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.auth import HTTPBasicAuth
|
||||
|
||||
agent = Agent(
|
||||
@@ -172,7 +197,7 @@ agent = Agent(
|
||||
goal="Coordinate with basic auth agents",
|
||||
backstory="Manages basic authentication communications",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://basic-agent.example.com/.well-known/agent-card.json",
|
||||
auth=HTTPBasicAuth(
|
||||
username="your-username",
|
||||
@@ -181,7 +206,7 @@ agent = Agent(
|
||||
timeout=120
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
@@ -190,7 +215,7 @@ agent = Agent(
|
||||
Configure multiple A2A agents for delegation by passing a list:
|
||||
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.auth import BearerTokenAuth
|
||||
|
||||
agent = Agent(
|
||||
@@ -199,11 +224,11 @@ agent = Agent(
|
||||
backstory="Expert at delegating to the right specialist",
|
||||
llm="gpt-4o",
|
||||
a2a=[
|
||||
A2AConfig(
|
||||
A2AClientConfig(
|
||||
endpoint="https://research.example.com/.well-known/agent-card.json",
|
||||
timeout=120
|
||||
),
|
||||
A2AConfig(
|
||||
A2AClientConfig(
|
||||
endpoint="https://data.example.com/.well-known/agent-card.json",
|
||||
auth=BearerTokenAuth(token="data-token"),
|
||||
timeout=90
|
||||
@@ -219,7 +244,7 @@ The LLM will automatically choose which A2A agent to delegate to based on the ta
|
||||
Control how agent connection failures are handled using the `fail_fast` parameter:
|
||||
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
from crewai.a2a import A2AClientConfig
|
||||
|
||||
# Fail immediately on connection errors (default)
|
||||
agent = Agent(
|
||||
@@ -227,7 +252,7 @@ agent = Agent(
|
||||
goal="Coordinate research tasks",
|
||||
backstory="Expert at delegation",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://research.example.com/.well-known/agent-card.json",
|
||||
fail_fast=True
|
||||
)
|
||||
@@ -240,11 +265,11 @@ agent = Agent(
|
||||
backstory="Expert at working with available resources",
|
||||
llm="gpt-4o",
|
||||
a2a=[
|
||||
A2AConfig(
|
||||
A2AClientConfig(
|
||||
endpoint="https://primary.example.com/.well-known/agent-card.json",
|
||||
fail_fast=False
|
||||
),
|
||||
A2AConfig(
|
||||
A2AClientConfig(
|
||||
endpoint="https://backup.example.com/.well-known/agent-card.json",
|
||||
fail_fast=False
|
||||
)
|
||||
@@ -263,8 +288,8 @@ Control how your agent receives task status updates from remote A2A agents:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Streaming (Default)">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python streaming_config.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.updates import StreamingConfig
|
||||
|
||||
agent = Agent(
|
||||
@@ -272,17 +297,17 @@ agent = Agent(
|
||||
goal="Coordinate research tasks",
|
||||
backstory="Expert at delegation",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://research.example.com/.well-known/agent-card.json",
|
||||
updates=StreamingConfig()
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Polling">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python polling_config.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.updates import PollingConfig
|
||||
|
||||
agent = Agent(
|
||||
@@ -290,7 +315,7 @@ agent = Agent(
|
||||
goal="Coordinate research tasks",
|
||||
backstory="Expert at delegation",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://research.example.com/.well-known/agent-card.json",
|
||||
updates=PollingConfig(
|
||||
interval=2.0,
|
||||
@@ -299,12 +324,12 @@ agent = Agent(
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Push Notifications">
|
||||
```python Code
|
||||
from crewai.a2a import A2AConfig
|
||||
```python push_notifications_config.py lines
|
||||
from crewai.a2a import A2AClientConfig
|
||||
from crewai.a2a.updates import PushNotificationConfig
|
||||
|
||||
agent = Agent(
|
||||
@@ -312,19 +337,137 @@ agent = Agent(
|
||||
goal="Coordinate research tasks",
|
||||
backstory="Expert at delegation",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AConfig(
|
||||
a2a=A2AClientConfig(
|
||||
endpoint="https://research.example.com/.well-known/agent-card.json",
|
||||
updates=PushNotificationConfig(
|
||||
url={base_url}/a2a/callback",
|
||||
url="{base_url}/a2a/callback",
|
||||
token="your-validation-token",
|
||||
timeout=300.0
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Exposing Agents as A2A Servers
|
||||
|
||||
You can expose your CrewAI agents as A2A-compliant servers, allowing other A2A clients to delegate tasks to them.
|
||||
|
||||
### Server Configuration
|
||||
|
||||
Add an `A2AServerConfig` to your agent to enable server capabilities:
|
||||
|
||||
```python a2a_server_agent.py lines
|
||||
from crewai import Agent
|
||||
from crewai.a2a import A2AServerConfig
|
||||
|
||||
agent = Agent(
|
||||
role="Data Analyst",
|
||||
goal="Analyze datasets and provide insights",
|
||||
backstory="Expert data scientist with statistical analysis skills",
|
||||
llm="gpt-4o",
|
||||
a2a=A2AServerConfig(url="https://your-server.com")
|
||||
)
|
||||
```
|
||||
|
||||
### Server Configuration Options
|
||||
|
||||
<ParamField path="name" type="str" default="None">
|
||||
Human-readable name for the agent. Defaults to the agent's role if not provided.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="description" type="str" default="None">
|
||||
Human-readable description. Defaults to the agent's goal and backstory if not provided.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="version" type="str" default="1.0.0">
|
||||
Version string for the agent card.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="skills" type="list[AgentSkill]" default="[]">
|
||||
List of agent skills. Auto-generated from agent tools if not provided.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="capabilities" type="AgentCapabilities" default="AgentCapabilities(streaming=True, push_notifications=False)">
|
||||
Declaration of optional capabilities supported by the agent.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="default_input_modes" type="list[str]" default='["text/plain", "application/json"]'>
|
||||
Supported input MIME types.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="default_output_modes" type="list[str]" default='["text/plain", "application/json"]'>
|
||||
Supported output MIME types.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="url" type="str" default="None">
|
||||
Preferred endpoint URL. If set, overrides the URL passed to `to_agent_card()`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="preferred_transport" type="Literal['JSONRPC', 'GRPC', 'HTTP+JSON']" default="JSONRPC">
|
||||
Transport protocol for the preferred endpoint.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="protocol_version" type="str" default="0.3">
|
||||
A2A protocol version this agent supports.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="provider" type="AgentProvider" default="None">
|
||||
Information about the agent's service provider.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="documentation_url" type="str" default="None">
|
||||
URL to the agent's documentation.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="icon_url" type="str" default="None">
|
||||
URL to an icon for the agent.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="additional_interfaces" type="list[AgentInterface]" default="[]">
|
||||
Additional supported interfaces (transport and URL combinations).
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="security" type="list[dict[str, list[str]]]" default="[]">
|
||||
Security requirement objects for all agent interactions.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="security_schemes" type="dict[str, SecurityScheme]" default="{}">
|
||||
Security schemes available to authorize requests.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="supports_authenticated_extended_card" type="bool" default="False">
|
||||
Whether agent provides extended card to authenticated users.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="signatures" type="list[AgentCardSignature]" default="[]">
|
||||
JSON Web Signatures for the AgentCard.
|
||||
</ParamField>
|
||||
|
||||
### Combined Client and Server
|
||||
|
||||
An agent can act as both client and server by providing both configurations:
|
||||
|
||||
```python Code
|
||||
from crewai import Agent
|
||||
from crewai.a2a import A2AClientConfig, A2AServerConfig
|
||||
|
||||
agent = Agent(
|
||||
role="Research Coordinator",
|
||||
goal="Coordinate research and serve analysis requests",
|
||||
backstory="Expert at delegation and analysis",
|
||||
llm="gpt-4o",
|
||||
a2a=[
|
||||
A2AClientConfig(
|
||||
endpoint="https://specialist.example.com/.well-known/agent-card.json",
|
||||
timeout=120
|
||||
),
|
||||
A2AServerConfig(url="https://your-server.com")
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
<CardGroup cols={2}>
|
||||
|
||||
@@ -151,3 +151,9 @@ HITL workflows are particularly valuable for:
|
||||
- Sensitive or high-stakes operations
|
||||
- Creative tasks requiring human judgment
|
||||
- Compliance and regulatory reviews
|
||||
|
||||
## Enterprise Features
|
||||
|
||||
<Card title="Flow HITL Management Platform" icon="users-gear" href="/en/enterprise/features/flow-hitl-management">
|
||||
CrewAI Enterprise provides a comprehensive HITL management system for Flows with in-platform review, responder assignment, permissions, escalation policies, SLA management, dynamic routing, and full analytics. [Learn more →](/en/enterprise/features/flow-hitl-management)
|
||||
</Card>
|
||||
|
||||
115
docs/en/observability/galileo.mdx
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: Galileo
|
||||
description: Galileo integration for CrewAI tracing and evaluation
|
||||
icon: telescope
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This guide demonstrates how to integrate **Galileo** with **CrewAI**
|
||||
for comprehensive tracing and Evaluation Engineering.
|
||||
By the end of this guide, you will be able to trace your CrewAI agents,
|
||||
monitor their performance, and evaluate their behaviour with
|
||||
Galileo's powerful observability platform.
|
||||
|
||||
> **What is Galileo?** [Galileo](https://galileo.ai) is AI evaluation and observability
|
||||
platform that delivers end-to-end tracing, evaluation,
|
||||
and monitoring for AI applications. It enables teams to capture ground truth,
|
||||
create robust guardrails, and run systematic experiments with
|
||||
built-in experiment tracking and performance analytics—ensuring reliability,
|
||||
transparency, and continuous improvement across the AI lifecycle.
|
||||
|
||||
## Getting started
|
||||
|
||||
This tutorial follows the [CrewAI quickstart](/en/quickstart) and shows how to add
|
||||
Galileo's [CrewAIEventListener](https://v2docs.galileo.ai/sdk-api/python/reference/handlers/crewai/handler),
|
||||
an event handler.
|
||||
For more information, see Galileo’s
|
||||
[Add Galileo to a CrewAI Application](https://v2docs.galileo.ai/how-to-guides/third-party-integrations/add-galileo-to-crewai/add-galileo-to-crewai)
|
||||
how-to guide.
|
||||
|
||||
> **Note** This tutorial assumes you have completed the [CrewAI quickstart](/en/quickstart).
|
||||
If you want a completed comprehensive example, see the Galileo
|
||||
[CrewAI sdk-example repo](https://github.com/rungalileo/sdk-examples/tree/main/python/agent/crew-ai).
|
||||
|
||||
### Step 1: Install dependencies
|
||||
|
||||
Install the required dependencies for your app.
|
||||
Create a virtual environment using your preferred method,
|
||||
then install dependencies inside that environment using your
|
||||
preferred tool:
|
||||
|
||||
```bash
|
||||
uv add galileo
|
||||
```
|
||||
|
||||
### Step 2: Add to the .env file from the [CrewAI quickstart](/en/quickstart)
|
||||
|
||||
```bash
|
||||
# Your Galileo API key
|
||||
GALILEO_API_KEY="your-galileo-api-key"
|
||||
|
||||
# Your Galileo project name
|
||||
GALILEO_PROJECT="your-galileo-project-name"
|
||||
|
||||
# The name of the Log stream you want to use for logging
|
||||
GALILEO_LOG_STREAM="your-galileo-log-stream "
|
||||
```
|
||||
|
||||
### Step 3: Add the Galileo event listener
|
||||
|
||||
To enable logging with Galileo, you need to create an instance of the `CrewAIEventListener`.
|
||||
Import the Galileo CrewAI handler package by
|
||||
adding the following code at the top of your main.py file:
|
||||
|
||||
```python
|
||||
from galileo.handlers.crewai.handler import CrewAIEventListener
|
||||
```
|
||||
|
||||
At the start of your run function, create the event listener:
|
||||
|
||||
```python
|
||||
def run():
|
||||
# Create the event listener
|
||||
CrewAIEventListener()
|
||||
# The rest of your existing code goes here
|
||||
```
|
||||
|
||||
When you create the listener instance, it is automatically
|
||||
registered with CrewAI.
|
||||
|
||||
### Step 4: Run your crew
|
||||
|
||||
Run your crew with the CrewAI CLI:
|
||||
|
||||
```bash
|
||||
crewai run
|
||||
```
|
||||
|
||||
### Step 5: View the traces in Galileo
|
||||
|
||||
Once your crew has finished, the traces will be flushed and appear in Galileo.
|
||||
|
||||

|
||||
|
||||
## Understanding the Galileo Integration
|
||||
|
||||
Galileo integrates with CrewAI by registering an event listener
|
||||
that captures Crew execution events (e.g., agent actions, tool calls, model responses)
|
||||
and forwards them to Galileo for observability and evaluation.
|
||||
|
||||
### Understanding the event listener
|
||||
|
||||
Creating a `CrewAIEventListener()` instance is all that’s
|
||||
required to enable Galileo for a CrewAI run. When instantiated, the listener:
|
||||
|
||||
- Automatically registers itself with CrewAI
|
||||
- Reads Galileo configuration from environment variables
|
||||
- Logs all run data to the Galileo project and log stream specified by
|
||||
`GALILEO_PROJECT` and `GALILEO_LOG_STREAM`
|
||||
|
||||
No additional configuration or code changes are required.
|
||||
All data from this run is logged to the Galileo project and
|
||||
log stream specified by your environment configuration
|
||||
(for example, GALILEO_PROJECT and GALILEO_LOG_STREAM).
|
||||
@@ -15,6 +15,29 @@ Along with that provides the ability for the Agent to update the database based
|
||||
|
||||
**Attention**: Make sure that the Agent has access to a Read-Replica or that is okay for the Agent to run insert/update queries on the database.
|
||||
|
||||
## Security Model
|
||||
|
||||
`NL2SQLTool` is an execution-capable tool. It runs model-generated SQL directly against the configured database connection.
|
||||
|
||||
This means risk depends on your deployment choices:
|
||||
|
||||
- Which credentials you provide in `db_uri`
|
||||
- Whether untrusted input can influence prompts
|
||||
- Whether you add tool-call guardrails before execution
|
||||
|
||||
If you route untrusted input to agents using this tool, treat it as a high-risk integration.
|
||||
|
||||
## Hardening Recommendations
|
||||
|
||||
Use all of the following in production:
|
||||
|
||||
- Use a read-only database user whenever possible
|
||||
- Prefer a read replica for analytics/retrieval workloads
|
||||
- Grant least privilege (no superuser/admin roles, no file/system-level capabilities)
|
||||
- Apply database-side resource limits (statement timeout, lock timeout, cost/row limits)
|
||||
- Add `before_tool_call` hooks to enforce allowed query patterns
|
||||
- Enable query logging and alerting for destructive statements
|
||||
|
||||
## Requirements
|
||||
|
||||
- SqlAlchemy
|
||||
|
||||
BIN
docs/images/enterprise/hitl-list-pending-feedbacks.png
Normal file
|
After Width: | Height: | Size: 251 KiB |
BIN
docs/images/enterprise/hitl-metrics.png
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
docs/images/enterprise/hitl-settings-auto-respond.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/images/enterprise/hitl-settings-overview.png
Normal file
|
After Width: | Height: | Size: 405 KiB |
BIN
docs/images/enterprise/hitl-settings-routing-rules.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
docs/images/enterprise/hitl-settings-webhook.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
docs/images/galileo-trace-veiw.png
Normal file
|
After Width: | Height: | Size: 239 KiB |
@@ -4,6 +4,74 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 1월 26일">
|
||||
## v1.9.0
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.9.0)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 프로바이더 전반에 걸친 구조화된 출력 및 response_format 지원 추가
|
||||
- 스트리밍 응답에 응답 ID 추가
|
||||
- 부모-자식 계층 구조를 가진 이벤트 순서 추가
|
||||
- Keycloak SSO 인증 지원 추가
|
||||
- 멀티모달 파일 처리 기능 추가
|
||||
- 네이티브 OpenAI responses API 지원 추가
|
||||
- A2A 작업 실행 유틸리티 추가
|
||||
- A2A 서버 구성 및 에이전트 카드 생성 추가
|
||||
- 이벤트 시스템 향상 및 전송 옵션 확장
|
||||
- 도구 호출 메커니즘 개선
|
||||
|
||||
### 버그 수정
|
||||
- aiocache를 사용할 수 없을 때 폴백 메모리 캐시로 파일 저장소 향상
|
||||
- 문서 목록이 비어 있지 않도록 보장
|
||||
- Bedrock 중지 시퀀스 적절히 처리
|
||||
- Google Vertex API 키 지원 추가
|
||||
- Azure 모델 중지 단어 감지 향상
|
||||
- 흐름 실행 시 HumanFeedbackPending 오류 처리 개선
|
||||
- 실행 스팬 작업 연결 해제 수정
|
||||
|
||||
### 문서
|
||||
- 네이티브 파일 처리 문서 추가
|
||||
- OpenAI responses API 문서 추가
|
||||
- 에이전트 카드 구현 가이드 추가
|
||||
- A2A 문서 개선
|
||||
- v1.8.0 변경 로그 업데이트
|
||||
|
||||
### 기여자
|
||||
@Anaisdg, @GininDenis, @Vidit-Ostwal, @greysonlalonde, @heitorado, @joaomdmoura, @koushiv777, @lorenzejay, @nicoferdi96, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 1월 15일">
|
||||
## v1.8.1
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.8.1)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- A2A 작업 실행 유틸리티 추가
|
||||
- A2A 서버 구성 및 에이전트 카드 생성 추가
|
||||
- 추가 전송 메커니즘 추가
|
||||
- Galileo 통합 지원 추가
|
||||
|
||||
### 버그 수정
|
||||
- Azure 모델 호환성 개선
|
||||
- parent_flow 감지를 위한 프레임 검사 깊이 확장
|
||||
- 작업 실행 스팬 관리 문제 해결
|
||||
- 흐름 실행 중 휴먼 피드백 시나리오에 대한 오류 처리 향상
|
||||
|
||||
### 문서
|
||||
- A2A 에이전트 카드 문서 추가
|
||||
- PII 삭제 기능 문서 추가
|
||||
|
||||
### 기여자
|
||||
@Anaisdg, @GininDenis, @greysonlalonde, @joaomdmoura, @koushiv777, @lorenzejay, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 1월 8일">
|
||||
## v1.8.0
|
||||
|
||||
|
||||
267
docs/ko/concepts/files.mdx
Normal file
@@ -0,0 +1,267 @@
|
||||
---
|
||||
title: 파일
|
||||
description: 멀티모달 처리를 위해 이미지, PDF, 오디오, 비디오, 텍스트 파일을 에이전트에 전달하세요.
|
||||
icon: file-image
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
CrewAI는 네이티브 멀티모달 파일 입력을 지원하여 이미지, PDF, 오디오, 비디오, 텍스트 파일을 에이전트에 직접 전달할 수 있습니다. 파일은 각 LLM 프로바이더의 API 요구사항에 맞게 자동으로 포맷됩니다.
|
||||
|
||||
<Note type="info" title="선택적 의존성">
|
||||
파일 지원을 위해서는 선택적 `crewai-files` 패키지가 필요합니다. 다음 명령어로 설치하세요:
|
||||
|
||||
```bash
|
||||
uv add 'crewai[file-processing]'
|
||||
```
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="얼리 액세스">
|
||||
파일 처리 API는 현재 얼리 액세스 단계입니다.
|
||||
</Note>
|
||||
|
||||
## 파일 타입
|
||||
|
||||
CrewAI는 5가지 특정 파일 타입과 타입을 자동 감지하는 일반 `File` 클래스를 지원합니다:
|
||||
|
||||
| 타입 | 클래스 | 사용 사례 |
|
||||
|:-----|:------|:----------|
|
||||
| **이미지** | `ImageFile` | 사진, 스크린샷, 다이어그램, 차트 |
|
||||
| **PDF** | `PDFFile` | 문서, 보고서, 논문 |
|
||||
| **오디오** | `AudioFile` | 음성 녹음, 팟캐스트, 회의 |
|
||||
| **비디오** | `VideoFile` | 화면 녹화, 프레젠테이션 |
|
||||
| **텍스트** | `TextFile` | 코드 파일, 로그, 데이터 파일 |
|
||||
| **일반** | `File` | 콘텐츠에서 타입 자동 감지 |
|
||||
|
||||
```python
|
||||
from crewai_files import File, ImageFile, PDFFile, AudioFile, VideoFile, TextFile
|
||||
|
||||
image = ImageFile(source="screenshot.png")
|
||||
pdf = PDFFile(source="report.pdf")
|
||||
audio = AudioFile(source="meeting.mp3")
|
||||
video = VideoFile(source="demo.mp4")
|
||||
text = TextFile(source="data.csv")
|
||||
|
||||
file = File(source="document.pdf")
|
||||
```
|
||||
|
||||
## 파일 소스
|
||||
|
||||
`source` 파라미터는 여러 입력 타입을 받아들이고 적절한 핸들러를 자동으로 감지합니다:
|
||||
|
||||
### 경로에서
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="./images/chart.png")
|
||||
```
|
||||
|
||||
### URL에서
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="https://example.com/image.png")
|
||||
```
|
||||
|
||||
### 바이트에서
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, FileBytes
|
||||
|
||||
image_bytes = download_image_from_api()
|
||||
image = ImageFile(source=FileBytes(data=image_bytes, filename="downloaded.png"))
|
||||
image = ImageFile(source=image_bytes)
|
||||
```
|
||||
|
||||
## 파일 사용하기
|
||||
|
||||
파일은 여러 레벨에서 전달할 수 있으며, 더 구체적인 레벨이 우선순위를 가집니다.
|
||||
|
||||
### Crew와 함께
|
||||
|
||||
crew를 킥오프할 때 파일을 전달합니다:
|
||||
|
||||
```python
|
||||
from crewai import Crew
|
||||
from crewai_files import ImageFile
|
||||
|
||||
crew = Crew(agents=[analyst], tasks=[analysis_task])
|
||||
|
||||
result = crew.kickoff(
|
||||
inputs={"topic": "Q4 Sales"},
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
"report": PDFFile(source="quarterly_report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Task와 함께
|
||||
|
||||
특정 작업에 파일을 첨부합니다:
|
||||
|
||||
```python
|
||||
from crewai import Task
|
||||
from crewai_files import ImageFile
|
||||
|
||||
task = Task(
|
||||
description="매출 차트를 분석하고 {chart}에서 트렌드를 파악하세요",
|
||||
expected_output="주요 트렌드 요약",
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Flow와 함께
|
||||
|
||||
flow에 파일을 전달하면 자동으로 crew에 상속됩니다:
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai_files import ImageFile
|
||||
|
||||
class AnalysisFlow(Flow):
|
||||
@start()
|
||||
def analyze(self):
|
||||
return self.analysis_crew.kickoff()
|
||||
|
||||
flow = AnalysisFlow()
|
||||
result = flow.kickoff(
|
||||
input_files={"image": ImageFile(source="data.png")}
|
||||
)
|
||||
```
|
||||
|
||||
### 단독 에이전트와 함께
|
||||
|
||||
에이전트 킥오프에 직접 파일을 전달합니다:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai_files import ImageFile
|
||||
|
||||
agent = Agent(
|
||||
role="Image Analyst",
|
||||
goal="Analyze images",
|
||||
backstory="Expert at visual analysis",
|
||||
llm="gpt-4o",
|
||||
)
|
||||
|
||||
result = agent.kickoff(
|
||||
messages="What's in this image?",
|
||||
input_files={"photo": ImageFile(source="photo.jpg")},
|
||||
)
|
||||
```
|
||||
|
||||
## 파일 우선순위
|
||||
|
||||
여러 레벨에서 파일이 전달될 때, 더 구체적인 레벨이 상위 레벨을 오버라이드합니다:
|
||||
|
||||
```
|
||||
Flow input_files < Crew input_files < Task input_files
|
||||
```
|
||||
|
||||
예를 들어, Flow와 Task 모두 `"chart"`라는 이름의 파일을 정의하면, Task의 버전이 사용됩니다.
|
||||
|
||||
## 프로바이더 지원
|
||||
|
||||
각 프로바이더는 서로 다른 파일 타입을 지원합니다. CrewAI는 각 프로바이더의 API에 맞게 파일을 자동으로 포맷합니다.
|
||||
|
||||
| 프로바이더 | 이미지 | PDF | 오디오 | 비디오 | 텍스트 |
|
||||
|:---------|:-----:|:---:|:-----:|:-----:|:----:|
|
||||
| **OpenAI** (completions API) | ✓ | | | | |
|
||||
| **OpenAI** (responses API) | ✓ | ✓ | ✓ | | |
|
||||
| **Anthropic** (claude-3.x) | ✓ | ✓ | | | |
|
||||
| **Google Gemini** (gemini-1.5, 2.0, 2.5) | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| **AWS Bedrock** (claude-3) | ✓ | ✓ | | | |
|
||||
| **Azure OpenAI** (gpt-4o) | ✓ | | ✓ | | |
|
||||
|
||||
<Note type="info" title="최대 파일 지원을 위한 Gemini">
|
||||
Google Gemini 모델은 비디오를 포함한 모든 파일 타입을 지원합니다 (최대 1시간, 2GB). 비디오 콘텐츠를 처리해야 할 때 Gemini를 사용하세요.
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="지원되지 않는 파일 타입">
|
||||
프로바이더가 지원하지 않는 파일 타입을 전달하면 (예: OpenAI에 비디오) `UnsupportedFileTypeError`가 발생합니다. 처리해야 하는 파일 타입에 따라 프로바이더를 선택하세요.
|
||||
</Note>
|
||||
|
||||
## 파일 전송 방식
|
||||
|
||||
CrewAI는 각 프로바이더에 파일을 전송하는 최적의 방법을 자동으로 선택합니다:
|
||||
|
||||
| 방식 | 설명 | 사용 조건 |
|
||||
|:-------|:------------|:----------|
|
||||
| **인라인 Base64** | 파일이 요청에 직접 임베드됨 | 작은 파일 (일반적으로 < 5MB) |
|
||||
| **파일 업로드 API** | 파일이 별도로 업로드되고 ID로 참조됨 | 임계값을 초과하는 큰 파일 |
|
||||
| **URL 참조** | 직접 URL이 모델에 전달됨 | 파일 소스가 이미 URL인 경우 |
|
||||
|
||||
### 프로바이더 전송 방식
|
||||
|
||||
| 프로바이더 | 인라인 Base64 | 파일 업로드 API | URL 참조 |
|
||||
|:---------|:-------------:|:---------------:|:--------------:|
|
||||
| **OpenAI** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Anthropic** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Google Gemini** | ✓ | ✓ (> 20 MB) | ✓ |
|
||||
| **AWS Bedrock** | ✓ | | ✓ (S3 URI) |
|
||||
| **Azure OpenAI** | ✓ | | ✓ |
|
||||
|
||||
<Note type="info" title="자동 최적화">
|
||||
이를 직접 관리할 필요가 없습니다. CrewAI는 파일 크기와 프로바이더 기능에 따라 가장 효율적인 방법을 자동으로 사용합니다. 파일 업로드 API가 없는 프로바이더는 모든 파일에 인라인 base64를 사용합니다.
|
||||
</Note>
|
||||
|
||||
## 파일 처리 모드
|
||||
|
||||
프로바이더 제한을 초과할 때 파일 처리 방식을 제어합니다:
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
image = ImageFile(source="large.png", mode="strict")
|
||||
image = ImageFile(source="large.png", mode="auto")
|
||||
image = ImageFile(source="large.png", mode="warn")
|
||||
pdf = PDFFile(source="large.pdf", mode="chunk")
|
||||
```
|
||||
|
||||
## 프로바이더 제약사항
|
||||
|
||||
각 프로바이더는 파일 크기와 규격에 대한 특정 제한이 있습니다:
|
||||
|
||||
### OpenAI
|
||||
- **이미지**: 최대 20 MB, 요청당 최대 10개 이미지
|
||||
- **PDF**: 최대 32 MB, 최대 100 페이지
|
||||
- **오디오**: 최대 25 MB, 최대 25분
|
||||
|
||||
### Anthropic
|
||||
- **이미지**: 최대 5 MB, 최대 8000x8000 픽셀, 최대 100개 이미지
|
||||
- **PDF**: 최대 32 MB, 최대 100 페이지
|
||||
|
||||
### Google Gemini
|
||||
- **이미지**: 최대 100 MB
|
||||
- **PDF**: 최대 50 MB
|
||||
- **오디오**: 최대 100 MB, 최대 9.5시간
|
||||
- **비디오**: 최대 2 GB, 최대 1시간
|
||||
|
||||
### AWS Bedrock
|
||||
- **이미지**: 최대 4.5 MB, 최대 8000x8000 픽셀
|
||||
- **PDF**: 최대 3.75 MB, 최대 100 페이지
|
||||
|
||||
## 프롬프트에서 파일 참조하기
|
||||
|
||||
작업 설명에서 파일의 키 이름을 사용하여 파일을 참조합니다:
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="""
|
||||
제공된 자료를 분석하세요:
|
||||
1. {sales_chart}에서 차트 검토
|
||||
2. {quarterly_report}의 데이터와 교차 참조
|
||||
3. 주요 발견사항 요약
|
||||
""",
|
||||
expected_output="주요 인사이트가 포함된 분석 요약",
|
||||
input_files={
|
||||
"sales_chart": ImageFile(source="chart.png"),
|
||||
"quarterly_report": PDFFile(source="report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -107,7 +107,7 @@ CrewAI 코드 내에는 사용할 모델을 지정할 수 있는 여러 위치
|
||||
|
||||
## 공급자 구성 예시
|
||||
|
||||
CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양한 LLM 공급자를 지원합니다.
|
||||
CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양한 LLM 공급자를 지원합니다.
|
||||
이 섹션에서는 프로젝트의 요구에 가장 적합한 LLM을 선택, 구성, 최적화하는 데 도움이 되는 자세한 예시를 제공합니다.
|
||||
|
||||
<AccordionGroup>
|
||||
@@ -150,11 +150,42 @@ CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양
|
||||
| o1-mini | 128,000 토큰 | 빠른 추론, 복잡한 추론 |
|
||||
| o1-preview | 128,000 토큰 | 빠른 추론, 복잡한 추론 |
|
||||
| o1 | 200,000 토큰 | 빠른 추론, 복잡한 추론 |
|
||||
|
||||
**Responses API:**
|
||||
|
||||
OpenAI는 Chat Completions(기본값)와 새로운 Responses API, 두 가지 API를 제공합니다. Responses API는 네이티브 멀티모달 지원을 기반으로 처음부터 설계되었으며, 텍스트, 이미지, 오디오, 함수 호출이 모두 일급 객체입니다. 추론 모델에서 더 나은 성능을 제공하고 자동 체이닝 및 내장 도구와 같은 추가 기능을 지원합니다.
|
||||
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
# Chat Completions 대신 Responses API 사용
|
||||
llm = LLM(
|
||||
model="openai/gpt-4o",
|
||||
api="responses", # Responses API 활성화
|
||||
store=True, # 멀티턴을 위한 응답 저장 (선택사항)
|
||||
auto_chain=True, # 추론 모델용 자동 체이닝 (선택사항)
|
||||
)
|
||||
```
|
||||
|
||||
**Responses API 파라미터:**
|
||||
- `api`: Responses API를 사용하려면 `"responses"`로 설정 (기본값: `"completions"`)
|
||||
- `instructions`: 시스템 레벨 지침 (Responses API 전용)
|
||||
- `store`: 멀티턴 대화를 위한 응답 저장 여부
|
||||
- `previous_response_id`: 멀티턴을 위한 이전 응답 ID
|
||||
- `include`: 응답에 포함할 추가 데이터 (예: `["reasoning.encrypted_content"]`)
|
||||
- `builtin_tools`: OpenAI 내장 도구 목록: `"web_search"`, `"file_search"`, `"code_interpreter"`, `"computer_use"`
|
||||
- `parse_tool_outputs`: 파싱된 내장 도구 출력과 함께 구조화된 `ResponsesAPIResult` 반환
|
||||
- `auto_chain`: 멀티턴 대화를 위한 응답 ID 자동 추적 및 사용
|
||||
- `auto_chain_reasoning`: ZDR(제로 데이터 보존) 준수를 위한 암호화된 추론 항목 추적
|
||||
|
||||
<Tip>
|
||||
새 프로젝트, 특히 추론 모델(o1, o3, o4)을 사용하거나 [파일](/ko/concepts/files)에 대한 네이티브 멀티모달 지원이 필요한 경우 Responses API를 사용하세요.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Meta-Llama">
|
||||
Meta의 Llama API는 Meta의 대형 언어 모델 패밀리 접근을 제공합니다.
|
||||
API는 [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website)에서 사용할 수 있습니다.
|
||||
Meta의 Llama API는 Meta의 대형 언어 모델 패밀리 접근을 제공합니다.
|
||||
API는 [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website)에서 사용할 수 있습니다.
|
||||
`.env` 파일에 다음 환경 변수를 설정하십시오:
|
||||
|
||||
```toml Code
|
||||
@@ -207,11 +238,20 @@ CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양
|
||||
`.env` 파일에 API 키를 설정하십시오. 키가 필요하거나 기존 키를 찾으려면 [AI Studio](https://aistudio.google.com/apikey)를 확인하세요.
|
||||
|
||||
```toml .env
|
||||
# https://ai.google.dev/gemini-api/docs/api-key
|
||||
# Gemini API 사용 시 (다음 중 하나)
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
GEMINI_API_KEY=<your-api-key>
|
||||
|
||||
# Vertex AI Express 모드 사용 시 (API 키 인증)
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
|
||||
# Vertex AI 서비스 계정 사용 시
|
||||
GOOGLE_CLOUD_PROJECT=<your-project-id>
|
||||
GOOGLE_CLOUD_LOCATION=<location> # 기본값: us-central1
|
||||
```
|
||||
|
||||
CrewAI 프로젝트에서의 예시 사용법:
|
||||
**기본 사용법:**
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
@@ -221,6 +261,34 @@ CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양
|
||||
)
|
||||
```
|
||||
|
||||
**Vertex AI Express 모드 (API 키 인증):**
|
||||
|
||||
Vertex AI Express 모드를 사용하면 서비스 계정 자격 증명 대신 간단한 API 키 인증으로 Vertex AI를 사용할 수 있습니다. Vertex AI를 시작하는 가장 빠른 방법입니다.
|
||||
|
||||
Express 모드를 활성화하려면 `.env` 파일에 두 환경 변수를 모두 설정하세요:
|
||||
```toml .env
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
```
|
||||
|
||||
그런 다음 평소처럼 LLM을 사용하세요:
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
llm = LLM(
|
||||
model="gemini/gemini-2.0-flash",
|
||||
temperature=0.7
|
||||
)
|
||||
```
|
||||
|
||||
<Info>
|
||||
Express 모드 API 키를 받으려면:
|
||||
- 신규 Google Cloud 사용자: [Express 모드 API 키](https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey) 받기
|
||||
- 기존 Google Cloud 사용자: [서비스 계정에 바인딩된 Google Cloud API 키](https://cloud.google.com/docs/authentication/api-keys) 받기
|
||||
|
||||
자세한 내용은 [Vertex AI Express 모드 문서](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey)를 참조하세요.
|
||||
</Info>
|
||||
|
||||
### Gemini 모델
|
||||
|
||||
Google은 다양한 용도에 최적화된 강력한 모델을 제공합니다.
|
||||
@@ -476,7 +544,7 @@ CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양
|
||||
|
||||
<Accordion title="Local NVIDIA NIM Deployed using WSL2">
|
||||
|
||||
NVIDIA NIM을 이용하면 Windows 기기에서 WSL2(Windows Subsystem for Linux)를 통해 강력한 LLM을 로컬로 실행할 수 있습니다.
|
||||
NVIDIA NIM을 이용하면 Windows 기기에서 WSL2(Windows Subsystem for Linux)를 통해 강력한 LLM을 로컬로 실행할 수 있습니다.
|
||||
이 방식은 Nvidia GPU를 활용하여 프라이빗하고, 안전하며, 비용 효율적인 AI 추론을 클라우드 서비스에 의존하지 않고 구현할 수 있습니다.
|
||||
데이터 프라이버시, 오프라인 기능이 필요한 개발, 테스트, 또는 프로덕션 환경에 최적입니다.
|
||||
|
||||
@@ -954,4 +1022,4 @@ LLM 설정을 최대한 활용하는 방법을 알아보세요:
|
||||
llm = LLM(model="openai/gpt-4o") # 128K tokens
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Tabs>
|
||||
|
||||
@@ -128,7 +128,7 @@ Flow를 배포할 때 다음을 고려하세요:
|
||||
### CrewAI Enterprise
|
||||
Flow를 배포하는 가장 쉬운 방법은 CrewAI Enterprise를 사용하는 것입니다. 인프라, 인증 및 모니터링을 대신 처리합니다.
|
||||
|
||||
시작하려면 [배포 가이드](/ko/enterprise/guides/deploy-crew)를 확인하세요.
|
||||
시작하려면 [배포 가이드](/ko/enterprise/guides/deploy-to-amp)를 확인하세요.
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
|
||||
@@ -91,7 +91,7 @@ Git 없이 빠르게 배포 — 프로젝트 ZIP 패키지를 업로드하세요
|
||||
## 관련 문서
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="크루 배포" href="/ko/enterprise/guides/deploy-crew" icon="rocket">
|
||||
<Card title="크루 배포" href="/ko/enterprise/guides/deploy-to-amp" icon="rocket">
|
||||
GitHub 또는 ZIP 파일로 크루 배포
|
||||
</Card>
|
||||
<Card title="자동화 트리거" href="/ko/enterprise/guides/automation-triggers" icon="trigger">
|
||||
|
||||
@@ -79,7 +79,7 @@ Crew Studio는 자연어와 시각적 워크플로 에디터로 처음부터 자
|
||||
<Card title="크루 빌드" href="/ko/enterprise/guides/build-crew" icon="paintbrush">
|
||||
크루를 빌드하세요.
|
||||
</Card>
|
||||
<Card title="크루 배포" href="/ko/enterprise/guides/deploy-crew" icon="rocket">
|
||||
<Card title="크루 배포" href="/ko/enterprise/guides/deploy-to-amp" icon="rocket">
|
||||
GitHub 또는 ZIP 파일로 크루 배포.
|
||||
</Card>
|
||||
<Card title="React 컴포넌트 내보내기" href="/ko/enterprise/guides/react-component-export" icon="download">
|
||||
|
||||
563
docs/ko/enterprise/features/flow-hitl-management.mdx
Normal file
@@ -0,0 +1,563 @@
|
||||
---
|
||||
title: "Flow HITL 관리"
|
||||
description: "이메일 우선 알림, 라우팅 규칙 및 자동 응답 기능을 갖춘 Flow용 엔터프라이즈급 인간 검토"
|
||||
icon: "users-gear"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Flow HITL 관리 기능은 `@human_feedback` 데코레이터가 필요하며, **CrewAI 버전 1.8.0 이상**에서 사용할 수 있습니다. 이 기능은 Crew가 아닌 **Flow**에만 적용됩니다.
|
||||
</Note>
|
||||
|
||||
CrewAI Enterprise는 AI 워크플로우를 협업적인 인간-AI 프로세스로 전환하는 Flow용 포괄적인 Human-in-the-Loop(HITL) 관리 시스템을 제공합니다. 플랫폼은 **이메일 우선 아키텍처**를 사용하여 이메일 주소가 있는 누구나 플랫폼 계정 없이도 검토 요청에 응답할 수 있습니다.
|
||||
|
||||
## 개요
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="이메일 우선 설계" icon="envelope">
|
||||
응답자가 알림 이메일에 직접 회신하여 피드백 제공 가능
|
||||
</Card>
|
||||
<Card title="유연한 라우팅" icon="route">
|
||||
메서드 패턴 또는 Flow 상태에 따라 특정 이메일로 요청 라우팅
|
||||
</Card>
|
||||
<Card title="자동 응답" icon="clock">
|
||||
시간 내에 인간이 응답하지 않을 경우 자동 대체 응답 구성
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### 주요 이점
|
||||
|
||||
- **간단한 멘탈 모델**: 이메일 주소는 보편적이며 플랫폼 사용자나 역할을 관리할 필요 없음
|
||||
- **외부 응답자**: 플랫폼 사용자가 아니어도 이메일이 있는 누구나 응답 가능
|
||||
- **동적 할당**: Flow 상태에서 직접 담당자 이메일 가져오기 (예: `sales_rep_email`)
|
||||
- **간소화된 구성**: 설정할 항목이 적어 더 빠르게 가치 실현
|
||||
- **이메일이 주요 채널**: 대부분의 사용자는 대시보드 로그인보다 이메일로 응답하는 것을 선호
|
||||
|
||||
## Flow에서 인간 검토 포인트 설정
|
||||
|
||||
`@human_feedback` 데코레이터를 사용하여 Flow 내에 인간 검토 체크포인트를 구성합니다. 실행이 검토 포인트에 도달하면 시스템이 일시 중지되고, 담당자에게 이메일로 알리며, 응답을 기다립니다.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start, listen
|
||||
from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult
|
||||
|
||||
class ContentApprovalFlow(Flow):
|
||||
@start()
|
||||
def generate_content(self):
|
||||
# AI가 콘텐츠 생성
|
||||
return "Q1 캠페인용 마케팅 카피 생성..."
|
||||
|
||||
@listen(generate_content)
|
||||
@human_feedback(
|
||||
message="브랜드 준수를 위해 이 콘텐츠를 검토해 주세요:",
|
||||
emit=["approved", "rejected", "needs_revision"],
|
||||
)
|
||||
def review_content(self, content):
|
||||
return content
|
||||
|
||||
@listen("approved")
|
||||
def publish_content(self, result: HumanFeedbackResult):
|
||||
print(f"승인된 콘텐츠 게시 중. 검토자 노트: {result.feedback}")
|
||||
|
||||
@listen("rejected")
|
||||
def archive_content(self, result: HumanFeedbackResult):
|
||||
print(f"콘텐츠 거부됨. 사유: {result.feedback}")
|
||||
|
||||
@listen("needs_revision")
|
||||
def revise_content(self, result: HumanFeedbackResult):
|
||||
print(f"수정 요청: {result.feedback}")
|
||||
```
|
||||
|
||||
완전한 구현 세부 사항은 [Flow에서 인간 피드백](/ko/learn/human-feedback-in-flows) 가이드를 참조하세요.
|
||||
|
||||
### 데코레이터 파라미터
|
||||
|
||||
| 파라미터 | 유형 | 설명 |
|
||||
|---------|------|------|
|
||||
| `message` | `str` | 인간 검토자에게 표시되는 메시지 |
|
||||
| `emit` | `list[str]` | 유효한 응답 옵션 (UI에서 버튼으로 표시) |
|
||||
|
||||
## 플랫폼 구성
|
||||
|
||||
HITL 구성에 접근: **배포** → **설정** → **Human in the Loop 구성**
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-overview.png" alt="HITL 구성 설정" />
|
||||
</Frame>
|
||||
|
||||
### 이메일 알림
|
||||
|
||||
HITL 요청에 대한 이메일 알림을 활성화하거나 비활성화하는 토글입니다.
|
||||
|
||||
| 설정 | 기본값 | 설명 |
|
||||
|-----|-------|------|
|
||||
| 이메일 알림 | 활성화됨 | 피드백 요청 시 이메일 전송 |
|
||||
|
||||
<Note>
|
||||
비활성화되면 응답자는 대시보드 UI를 사용하거나 커스텀 알림 시스템을 위해 webhook을 구성해야 합니다.
|
||||
</Note>
|
||||
|
||||
### SLA 목표
|
||||
|
||||
추적 및 메트릭 목적으로 목표 응답 시간을 설정합니다.
|
||||
|
||||
| 설정 | 설명 |
|
||||
|-----|------|
|
||||
| SLA 목표 (분) | 목표 응답 시간. 대시보드 메트릭 및 SLA 추적에 사용 |
|
||||
|
||||
SLA 추적을 비활성화하려면 비워 두세요.
|
||||
|
||||
## 이메일 알림 및 응답
|
||||
|
||||
HITL 시스템은 응답자가 알림 이메일에 직접 회신할 수 있는 이메일 우선 아키텍처를 사용합니다.
|
||||
|
||||
### 이메일 응답 작동 방식
|
||||
|
||||
<Steps>
|
||||
<Step title="알림 전송">
|
||||
HITL 요청이 생성되면 검토 콘텐츠와 컨텍스트가 포함된 이메일이 할당된 응답자에게 전송됩니다.
|
||||
</Step>
|
||||
<Step title="Reply-To 주소">
|
||||
이메일에는 인증을 위한 서명된 토큰이 포함된 특별한 reply-to 주소가 있습니다.
|
||||
</Step>
|
||||
<Step title="사용자 회신">
|
||||
응답자는 이메일에 피드백으로 회신하면 됩니다—로그인 필요 없음.
|
||||
</Step>
|
||||
<Step title="토큰 검증">
|
||||
플랫폼이 회신을 받고, 서명된 토큰을 확인하고, 발신자 이메일을 매칭합니다.
|
||||
</Step>
|
||||
<Step title="Flow 재개">
|
||||
피드백이 기록되고 인간의 입력으로 Flow가 계속됩니다.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### 응답 형식
|
||||
|
||||
응답자는 다음과 같이 회신할 수 있습니다:
|
||||
|
||||
- **Emit 옵션**: 회신이 `emit` 옵션과 일치하면 (예: "approved") 직접 사용됨
|
||||
- **자유 형식 텍스트**: 모든 텍스트 응답이 피드백으로 Flow에 전달됨
|
||||
- **일반 텍스트**: 회신 본문의 첫 번째 줄이 피드백으로 사용됨
|
||||
|
||||
### 확인 이메일
|
||||
|
||||
회신을 처리한 후 응답자는 피드백이 성공적으로 제출되었는지 또는 오류가 발생했는지 나타내는 확인 이메일을 받습니다.
|
||||
|
||||
### 이메일 토큰 보안
|
||||
|
||||
- 토큰은 보안을 위해 암호화 서명됨
|
||||
- 토큰은 7일 후 만료됨
|
||||
- 발신자 이메일은 토큰의 인증된 이메일과 일치해야 함
|
||||
- 처리 후 확인/오류 이메일 전송됨
|
||||
|
||||
## 라우팅 규칙
|
||||
|
||||
메서드 패턴에 따라 HITL 요청을 특정 이메일 주소로 라우팅합니다.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-routing-rules.png" alt="HITL 라우팅 규칙 구성" />
|
||||
</Frame>
|
||||
|
||||
### 규칙 구조
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "재무팀으로 승인",
|
||||
"match": {
|
||||
"method_name": "approve_*"
|
||||
},
|
||||
"assign_to_email": "finance@company.com",
|
||||
"assign_from_input": "manager_email"
|
||||
}
|
||||
```
|
||||
|
||||
### 매칭 패턴
|
||||
|
||||
| 패턴 | 설명 | 매칭 예시 |
|
||||
|-----|------|----------|
|
||||
| `approve_*` | 와일드카드 (모든 문자) | `approve_payment`, `approve_vendor` |
|
||||
| `review_?` | 단일 문자 | `review_a`, `review_1` |
|
||||
| `validate_payment` | 정확히 일치 | `validate_payment`만 |
|
||||
|
||||
### 할당 우선순위
|
||||
|
||||
1. **동적 할당** (`assign_from_input`): 구성된 경우 Flow 상태에서 이메일 가져옴
|
||||
2. **정적 이메일** (`assign_to_email`): 구성된 이메일로 대체
|
||||
3. **배포 생성자**: 규칙이 일치하지 않으면 배포 생성자의 이메일이 사용됨
|
||||
|
||||
### 동적 할당 예제
|
||||
|
||||
Flow 상태에 `{"sales_rep_email": "alice@company.com"}`이 포함된 경우:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "영업 담당자에게 라우팅",
|
||||
"match": {
|
||||
"method_name": "review_*"
|
||||
},
|
||||
"assign_from_input": "sales_rep_email"
|
||||
}
|
||||
```
|
||||
|
||||
요청이 자동으로 `alice@company.com`에 할당됩니다.
|
||||
|
||||
<Tip>
|
||||
**사용 사례**: CRM, 데이터베이스 또는 이전 Flow 단계에서 담당자를 가져와 적합한 사람에게 검토를 동적으로 라우팅하세요.
|
||||
</Tip>
|
||||
|
||||
## 자동 응답
|
||||
|
||||
시간 내에 인간이 응답하지 않으면 HITL 요청에 자동으로 응답합니다. 이를 통해 Flow가 무한정 중단되지 않도록 합니다.
|
||||
|
||||
### 구성
|
||||
|
||||
| 설정 | 설명 |
|
||||
|-----|------|
|
||||
| 활성화됨 | 자동 응답 활성화 토글 |
|
||||
| 타임아웃 (분) | 자동 응답 전 대기 시간 |
|
||||
| 기본 결과 | 응답 값 (`emit` 옵션과 일치해야 함) |
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-auto-respond.png" alt="HITL 자동 응답 구성" />
|
||||
</Frame>
|
||||
|
||||
### 사용 사례
|
||||
|
||||
- **SLA 준수**: Flow가 무한정 중단되지 않도록 보장
|
||||
- **기본 승인**: 타임아웃 후 저위험 요청 자동 승인
|
||||
- **우아한 저하**: 검토자가 없을 때 안전한 기본값으로 계속
|
||||
|
||||
<Warning>
|
||||
자동 응답을 신중하게 사용하세요. 기본 응답이 허용되는 중요하지 않은 검토에만 활성화하세요.
|
||||
</Warning>
|
||||
|
||||
## 검토 프로세스
|
||||
|
||||
### 대시보드 인터페이스
|
||||
|
||||
HITL 검토 인터페이스는 검토자에게 깔끔하고 집중된 경험을 제공합니다:
|
||||
|
||||
- **마크다운 렌더링**: 구문 강조가 포함된 풍부한 형식의 검토 콘텐츠
|
||||
- **컨텍스트 패널**: Flow 상태, 실행 기록 및 관련 정보 보기
|
||||
- **피드백 입력**: 결정과 함께 상세한 피드백 및 코멘트 제공
|
||||
- **빠른 작업**: 선택적 코멘트가 있는 원클릭 emit 옵션 버튼
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-list-pending-feedbacks.png" alt="HITL 대기 중인 요청 목록" />
|
||||
</Frame>
|
||||
|
||||
### 응답 방법
|
||||
|
||||
검토자는 세 가지 채널을 통해 응답할 수 있습니다:
|
||||
|
||||
| 방법 | 설명 |
|
||||
|-----|------|
|
||||
| **이메일 회신** | 알림 이메일에 직접 회신 |
|
||||
| **대시보드** | Enterprise 대시보드 UI 사용 |
|
||||
| **API/Webhook** | API를 통한 프로그래밍 방식 응답 |
|
||||
|
||||
### 기록 및 감사 추적
|
||||
|
||||
모든 HITL 상호작용은 완전한 타임라인으로 추적됩니다:
|
||||
|
||||
- 결정 기록 (승인/거부/수정)
|
||||
- 검토자 신원 및 타임스탬프
|
||||
- 제공된 피드백 및 코멘트
|
||||
- 응답 방법 (이메일/대시보드/API)
|
||||
- 응답 시간 메트릭
|
||||
|
||||
## 분석 및 모니터링
|
||||
|
||||
포괄적인 분석으로 HITL 성능을 추적합니다.
|
||||
|
||||
### 성능 대시보드
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-metrics.png" alt="HITL 메트릭 대시보드" />
|
||||
</Frame>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="응답 시간" icon="stopwatch">
|
||||
검토자 또는 Flow별 평균 및 중앙값 응답 시간 모니터링.
|
||||
</Card>
|
||||
<Card title="볼륨 트렌드" icon="chart-bar">
|
||||
팀 용량 최적화를 위한 검토 볼륨 패턴 분석.
|
||||
</Card>
|
||||
<Card title="결정 분포" icon="chart-pie">
|
||||
다양한 검토 유형에 대한 승인/거부 비율 보기.
|
||||
</Card>
|
||||
<Card title="SLA 추적" icon="chart-line">
|
||||
SLA 목표 내에 완료된 검토 비율 추적.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### 감사 및 규정 준수
|
||||
|
||||
규제 요구 사항을 위한 엔터프라이즈급 감사 기능:
|
||||
|
||||
- 타임스탬프가 있는 완전한 결정 기록
|
||||
- 검토자 신원 확인
|
||||
- 불변 감사 로그
|
||||
- 규정 준수 보고를 위한 내보내기 기능
|
||||
|
||||
## 일반적인 사용 사례
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="보안 검토" icon="shield-halved">
|
||||
**사용 사례**: 인간 검증이 포함된 내부 보안 설문지 자동화
|
||||
|
||||
- AI가 보안 설문지에 대한 응답 생성
|
||||
- 보안팀이 이메일로 정확성 검토 및 검증
|
||||
- 승인된 응답이 최종 제출물로 편집
|
||||
- 규정 준수를 위한 완전한 감사 추적
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="콘텐츠 승인" icon="file-lines">
|
||||
**사용 사례**: 법무/브랜드 검토가 필요한 마케팅 콘텐츠
|
||||
|
||||
- AI가 마케팅 카피 또는 소셜 미디어 콘텐츠 생성
|
||||
- 브랜드팀 이메일로 목소리/톤 검토를 위해 라우팅
|
||||
- 승인 시 자동 게시
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="재무 승인" icon="money-bill">
|
||||
**사용 사례**: 경비 보고서, 계약 조건, 예산 배분
|
||||
|
||||
- AI가 재무 요청을 사전 처리하고 분류
|
||||
- 동적 할당을 사용하여 금액 임계값에 따라 라우팅
|
||||
- 재무 규정 준수를 위한 완전한 감사 추적 유지
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="CRM에서 동적 할당" icon="database">
|
||||
**사용 사례**: CRM에서 계정 담당자에게 검토 라우팅
|
||||
|
||||
- Flow가 CRM에서 계정 담당자 이메일 가져옴
|
||||
- 이메일을 Flow 상태에 저장 (예: `account_owner_email`)
|
||||
- `assign_from_input`을 사용하여 적합한 사람에게 자동 라우팅
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="품질 보증" icon="magnifying-glass">
|
||||
**사용 사례**: 고객 전달 전 AI 출력 검증
|
||||
|
||||
- AI가 고객 대면 콘텐츠 또는 응답 생성
|
||||
- QA팀이 이메일 알림을 통해 검토
|
||||
- 피드백 루프가 시간이 지남에 따라 AI 성능 개선
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Webhook API
|
||||
|
||||
Flow가 인간 피드백을 위해 일시 중지되면, 요청 데이터를 자체 애플리케이션으로 보내도록 webhook을 구성할 수 있습니다. 이를 통해 다음이 가능합니다:
|
||||
|
||||
- 커스텀 승인 UI 구축
|
||||
- 내부 도구와 통합 (Jira, ServiceNow, 커스텀 대시보드)
|
||||
- 타사 시스템으로 승인 라우팅
|
||||
- 모바일 앱 알림
|
||||
- 자동화된 결정 시스템
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-webhook.png" alt="HITL Webhook 구성" />
|
||||
</Frame>
|
||||
|
||||
### Webhook 구성
|
||||
|
||||
<Steps>
|
||||
<Step title="설정으로 이동">
|
||||
**배포** → **설정** → **Human in the Loop**으로 이동
|
||||
</Step>
|
||||
<Step title="Webhook 섹션 확장">
|
||||
**Webhooks** 구성을 클릭하여 확장
|
||||
</Step>
|
||||
<Step title="Webhook URL 추가">
|
||||
webhook URL 입력 (프로덕션에서는 HTTPS 필수)
|
||||
</Step>
|
||||
<Step title="구성 저장">
|
||||
**구성 저장**을 클릭하여 활성화
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
여러 webhook을 구성할 수 있습니다. 각 활성 webhook은 모든 HITL 이벤트를 수신합니다.
|
||||
|
||||
### Webhook 이벤트
|
||||
|
||||
엔드포인트는 다음 이벤트에 대해 HTTP POST 요청을 수신합니다:
|
||||
|
||||
| 이벤트 유형 | 트리거 시점 |
|
||||
|------------|------------|
|
||||
| `new_request` | Flow가 일시 중지되고 인간 피드백을 요청할 때 |
|
||||
|
||||
### Webhook 페이로드
|
||||
|
||||
모든 webhook은 다음 구조의 JSON 페이로드를 수신합니다:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "new_request",
|
||||
"request": {
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"flow_id": "flow_abc123",
|
||||
"method_name": "review_article",
|
||||
"message": "이 기사의 게시를 검토해 주세요.",
|
||||
"emit_options": ["approved", "rejected", "request_changes"],
|
||||
"state": {
|
||||
"article_id": 12345,
|
||||
"author": "john@example.com",
|
||||
"category": "technology"
|
||||
},
|
||||
"metadata": {},
|
||||
"created_at": "2026-01-14T12:00:00Z"
|
||||
},
|
||||
"deployment": {
|
||||
"id": 456,
|
||||
"name": "Content Review Flow",
|
||||
"organization_id": 789
|
||||
},
|
||||
"callback_url": "https://api.crewai.com/...",
|
||||
"assigned_to_email": "reviewer@company.com"
|
||||
}
|
||||
```
|
||||
|
||||
### 요청에 응답하기
|
||||
|
||||
피드백을 제출하려면 webhook 페이로드에 포함된 **`callback_url`로 POST**합니다.
|
||||
|
||||
```http
|
||||
POST {callback_url}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"feedback": "승인됨. 훌륭한 기사입니다!",
|
||||
"source": "my_custom_app"
|
||||
}
|
||||
```
|
||||
|
||||
### 보안
|
||||
|
||||
<Info>
|
||||
모든 webhook 요청은 HMAC-SHA256을 사용하여 암호화 서명되어 진위성을 보장하고 변조를 방지합니다.
|
||||
</Info>
|
||||
|
||||
#### Webhook 보안
|
||||
|
||||
- **HMAC-SHA256 서명**: 모든 webhook에 암호화 서명이 포함됨
|
||||
- **Webhook별 시크릿**: 각 webhook은 고유한 서명 시크릿을 가짐
|
||||
- **저장 시 암호화**: 서명 시크릿은 데이터베이스에서 암호화됨
|
||||
- **타임스탬프 검증**: 리플레이 공격 방지
|
||||
|
||||
#### 서명 헤더
|
||||
|
||||
각 webhook 요청에는 다음 헤더가 포함됩니다:
|
||||
|
||||
| 헤더 | 설명 |
|
||||
|------|------|
|
||||
| `X-Signature` | HMAC-SHA256 서명: `sha256=<hex_digest>` |
|
||||
| `X-Timestamp` | 요청이 서명된 Unix 타임스탬프 |
|
||||
|
||||
#### 검증
|
||||
|
||||
다음과 같이 계산하여 검증합니다:
|
||||
|
||||
```python
|
||||
import hmac
|
||||
import hashlib
|
||||
|
||||
expected = hmac.new(
|
||||
signing_secret.encode(),
|
||||
f"{timestamp}.{payload}".encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
if hmac.compare_digest(expected, signature):
|
||||
# 유효한 서명
|
||||
```
|
||||
|
||||
### 오류 처리
|
||||
|
||||
webhook 엔드포인트는 수신 확인을 위해 2xx 상태 코드를 반환해야 합니다:
|
||||
|
||||
| 응답 | 동작 |
|
||||
|------|------|
|
||||
| 2xx | Webhook 성공적으로 전달됨 |
|
||||
| 4xx/5xx | 실패로 기록됨, 재시도 없음 |
|
||||
| 타임아웃 (30초) | 실패로 기록됨, 재시도 없음 |
|
||||
|
||||
## 보안 및 RBAC
|
||||
|
||||
### 대시보드 접근
|
||||
|
||||
HITL 접근은 배포 수준에서 제어됩니다:
|
||||
|
||||
| 권한 | 기능 |
|
||||
|-----|------|
|
||||
| `manage_human_feedback` | HITL 설정 구성, 모든 요청 보기 |
|
||||
| `respond_to_human_feedback` | 요청에 응답, 할당된 요청 보기 |
|
||||
|
||||
### 이메일 응답 인증
|
||||
|
||||
이메일 회신의 경우:
|
||||
1. reply-to 토큰이 인증된 이메일을 인코딩
|
||||
2. 발신자 이메일이 토큰의 이메일과 일치해야 함
|
||||
3. 토큰이 만료되지 않아야 함 (기본 7일)
|
||||
4. 요청이 여전히 대기 중이어야 함
|
||||
|
||||
### 감사 추적
|
||||
|
||||
모든 HITL 작업이 기록됩니다:
|
||||
- 요청 생성
|
||||
- 할당 변경
|
||||
- 응답 제출 (소스: 대시보드/이메일/API)
|
||||
- Flow 재개 상태
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 이메일이 전송되지 않음
|
||||
|
||||
1. 구성에서 "이메일 알림"이 활성화되어 있는지 확인
|
||||
2. 라우팅 규칙이 메서드 이름과 일치하는지 확인
|
||||
3. 담당자 이메일이 유효한지 확인
|
||||
4. 라우팅 규칙이 일치하지 않는 경우 배포 생성자 대체 확인
|
||||
|
||||
### 이메일 회신이 처리되지 않음
|
||||
|
||||
1. 토큰이 만료되지 않았는지 확인 (기본 7일)
|
||||
2. 발신자 이메일이 할당된 이메일과 일치하는지 확인
|
||||
3. 요청이 여전히 대기 중인지 확인 (아직 응답되지 않음)
|
||||
|
||||
### Flow가 재개되지 않음
|
||||
|
||||
1. 대시보드에서 요청 상태 확인
|
||||
2. 콜백 URL에 접근 가능한지 확인
|
||||
3. 배포가 여전히 실행 중인지 확인
|
||||
|
||||
## 모범 사례
|
||||
|
||||
<Tip>
|
||||
**간단하게 시작**: 배포 생성자에게 이메일 알림으로 시작한 다음, 워크플로우가 성숙해지면 라우팅 규칙을 추가하세요.
|
||||
</Tip>
|
||||
|
||||
1. **동적 할당 사용**: 유연한 라우팅을 위해 Flow 상태에서 담당자 이메일을 가져오세요.
|
||||
|
||||
2. **자동 응답 구성**: 중요하지 않은 검토에 대해 Flow가 중단되지 않도록 대체를 설정하세요.
|
||||
|
||||
3. **응답 시간 모니터링**: 분석을 사용하여 병목 현상을 식별하고 검토 프로세스를 최적화하세요.
|
||||
|
||||
4. **검토 메시지를 명확하게 유지**: `@human_feedback` 데코레이터에 명확하고 실행 가능한 메시지를 작성하세요.
|
||||
|
||||
5. **이메일 흐름 테스트**: 프로덕션에 가기 전에 테스트 요청을 보내 이메일 전달을 확인하세요.
|
||||
|
||||
## 관련 리소스
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Flow에서 인간 피드백" icon="code" href="/ko/learn/human-feedback-in-flows">
|
||||
`@human_feedback` 데코레이터 구현 가이드
|
||||
</Card>
|
||||
<Card title="Flow HITL 워크플로우 가이드" icon="route" href="/ko/enterprise/guides/human-in-the-loop">
|
||||
HITL 워크플로우 설정을 위한 단계별 가이드
|
||||
</Card>
|
||||
<Card title="RBAC 구성" icon="shield-check" href="/ko/enterprise/features/rbac">
|
||||
조직을 위한 역할 기반 접근 제어 구성
|
||||
</Card>
|
||||
<Card title="Webhook 스트리밍" icon="bolt" href="/ko/enterprise/features/webhook-streaming">
|
||||
실시간 이벤트 알림 설정
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,305 +0,0 @@
|
||||
---
|
||||
title: "Crew 배포"
|
||||
description: "CrewAI 엔터프라이즈에서 Crew 배포하기"
|
||||
icon: "rocket"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
로컬에서 또는 Crew Studio를 통해 crew를 생성한 후, 다음 단계는 이를 CrewAI AMP
|
||||
플랫폼에 배포하는 것입니다. 본 가이드에서는 다양한 배포 방법을 다루며,
|
||||
여러분의 워크플로우에 가장 적합한 방식을 선택할 수 있도록 안내합니다.
|
||||
</Note>
|
||||
|
||||
## 사전 준비 사항
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="배포 준비가 된 Crew" icon="users">
|
||||
작동 중인 crew가 로컬에서 빌드되었거나 Crew Studio를 통해 생성되어 있어야
|
||||
합니다.
|
||||
</Card>
|
||||
<Card title="GitHub 저장소" icon="github">
|
||||
crew 코드가 GitHub 저장소에 있어야 합니다(GitHub 연동 방식의 경우).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 옵션 1: CrewAI CLI를 사용한 배포
|
||||
|
||||
CLI는 로컬에서 개발된 crew를 Enterprise 플랫폼에 가장 빠르게 배포할 수 있는 방법을 제공합니다.
|
||||
|
||||
<Steps>
|
||||
<Step title="CrewAI CLI 설치">
|
||||
아직 설치하지 않았다면 CrewAI CLI를 설치하세요:
|
||||
|
||||
```bash
|
||||
pip install crewai[tools]
|
||||
```
|
||||
|
||||
<Tip>
|
||||
CLI는 기본 CrewAI 패키지에 포함되어 있지만, `[tools]` 추가 옵션을 사용하면 모든 배포 종속성을 함께 설치할 수 있습니다.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Enterprise 플랫폼에 인증">
|
||||
먼저, CrewAI AMP 플랫폼에 CLI를 인증해야 합니다:
|
||||
|
||||
```bash
|
||||
# 이미 CrewAI AMP 계정이 있거나 새로 생성하고 싶을 때:
|
||||
crewai login
|
||||
```
|
||||
|
||||
위 명령어를 실행하면 CLI가 다음을 진행합니다:
|
||||
1. URL과 고유 기기 코드를 표시합니다
|
||||
2. 브라우저를 열어 인증 페이지로 이동합니다
|
||||
3. 기기 확인을 요청합니다
|
||||
4. 인증 과정을 완료합니다
|
||||
|
||||
인증이 성공적으로 완료되면 터미널에 확인 메시지가 표시됩니다!
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="배포 생성">
|
||||
|
||||
프로젝트 디렉터리에서 다음 명령어를 실행하세요:
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
```
|
||||
|
||||
이 명령어는 다음을 수행합니다:
|
||||
1. GitHub 저장소 정보를 감지합니다
|
||||
2. 로컬 `.env` 파일의 환경 변수를 식별합니다
|
||||
3. 이러한 변수를 Enterprise 플랫폼으로 안전하게 전송합니다
|
||||
4. 고유 식별자가 부여된 새 배포를 만듭니다
|
||||
|
||||
성공적으로 생성되면 다음과 같은 메시지가 표시됩니다:
|
||||
```shell
|
||||
Deployment created successfully!
|
||||
Name: your_project_name
|
||||
Deployment ID: 01234567-89ab-cdef-0123-456789abcdef
|
||||
Current Status: Deploy Enqueued
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="배포 진행 상황 모니터링">
|
||||
|
||||
다음 명령어로 배포 상태를 추적할 수 있습니다:
|
||||
|
||||
```bash
|
||||
crewai deploy status
|
||||
```
|
||||
|
||||
빌드 과정의 상세 로그가 필요하다면:
|
||||
|
||||
```bash
|
||||
crewai deploy logs
|
||||
```
|
||||
|
||||
<Tip>
|
||||
첫 배포는 컨테이너 이미지를 빌드하므로 일반적으로 10~15분 정도 소요됩니다. 이후 배포는 훨씬 빠릅니다.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 추가 CLI 명령어
|
||||
|
||||
CrewAI CLI는 배포를 관리하기 위한 여러 명령어를 제공합니다:
|
||||
|
||||
```bash
|
||||
# 모든 배포 목록 확인
|
||||
crewai deploy list
|
||||
|
||||
# 배포 상태 확인
|
||||
crewai deploy status
|
||||
|
||||
# 배포 로그 보기
|
||||
crewai deploy logs
|
||||
|
||||
# 코드 변경 후 업데이트 푸시
|
||||
crewai deploy push
|
||||
|
||||
# 배포 삭제
|
||||
crewai deploy remove <deployment_id>
|
||||
```
|
||||
|
||||
## 옵션 2: 웹 인터페이스를 통한 직접 배포
|
||||
|
||||
GitHub 계정을 연결하여 CrewAI AMP 웹 인터페이스를 통해 crews를 직접 배포할 수도 있습니다. 이 방법은 로컬 머신에서 CLI를 사용할 필요가 없습니다.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="GitHub로 푸시하기">
|
||||
|
||||
crew를 GitHub 저장소에 푸시해야 합니다. 아직 crew를 만들지 않았다면, [이 튜토리얼](/ko/quickstart)을 따라할 수 있습니다.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="GitHub를 CrewAI AOP에 연결하기">
|
||||
|
||||
1. [CrewAI AMP](https://app.crewai.com)에 로그인합니다.
|
||||
2. "Connect GitHub" 버튼을 클릭합니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="저장소 선택하기">
|
||||
|
||||
GitHub 계정을 연결한 후 배포할 저장소를 선택할 수 있습니다:
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="환경 변수 설정하기">
|
||||
|
||||
배포 전에, LLM 제공업체 또는 기타 서비스에 연결할 환경 변수를 설정해야 합니다:
|
||||
|
||||
1. 변수를 개별적으로 또는 일괄적으로 추가할 수 있습니다.
|
||||
2. 환경 변수는 `KEY=VALUE` 형식(한 줄에 하나씩)으로 입력합니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Crew 배포하기">
|
||||
|
||||
1. "Deploy" 버튼을 클릭하여 배포 프로세스를 시작합니다.
|
||||
2. 진행 바를 통해 진행 상황을 모니터링할 수 있습니다.
|
||||
3. 첫 번째 배포에는 일반적으로 약 10-15분 정도 소요되며, 이후 배포는 더 빠릅니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
배포가 완료되면 다음을 확인할 수 있습니다:
|
||||
- crew의 고유 URL
|
||||
- crew API를 보호할 Bearer 토큰
|
||||
- 배포를 삭제해야 하는 경우 "Delete" 버튼
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## ⚠️ 환경 변수 보안 요구사항
|
||||
|
||||
<Warning>
|
||||
**중요**: CrewAI AOP는 환경 변수 이름에 대한 보안 제한이 있으며, 이를 따르지
|
||||
않을 경우 배포가 실패할 수 있습니다.
|
||||
</Warning>
|
||||
|
||||
### 차단된 환경 변수 패턴
|
||||
|
||||
보안상의 이유로, 다음과 같은 환경 변수 명명 패턴은 **자동으로 필터링**되며 배포에 문제가 발생할 수 있습니다:
|
||||
|
||||
**차단된 패턴:**
|
||||
|
||||
- `_TOKEN`으로 끝나는 변수 (예: `MY_API_TOKEN`)
|
||||
- `_PASSWORD`로 끝나는 변수 (예: `DB_PASSWORD`)
|
||||
- `_SECRET`로 끝나는 변수 (예: `API_SECRET`)
|
||||
- 특정 상황에서 `_KEY`로 끝나는 변수
|
||||
|
||||
**특정 차단 변수:**
|
||||
|
||||
- `GITHUB_USER`, `GITHUB_TOKEN`
|
||||
- `AWS_REGION`, `AWS_DEFAULT_REGION`
|
||||
- 다양한 내부 CrewAI 시스템 변수
|
||||
|
||||
### 허용된 예외
|
||||
|
||||
일부 변수는 차단된 패턴과 일치하더라도 명시적으로 허용됩니다:
|
||||
|
||||
- `AZURE_AD_TOKEN`
|
||||
- `AZURE_OPENAI_AD_TOKEN`
|
||||
- `ENTERPRISE_ACTION_TOKEN`
|
||||
- `CREWAI_ENTEPRISE_TOOLS_TOKEN`
|
||||
|
||||
### 네이밍 문제 해결 방법
|
||||
|
||||
환경 변수 제한으로 인해 배포가 실패하는 경우:
|
||||
|
||||
```bash
|
||||
# ❌ 이러한 이름은 배포 실패를 초래합니다
|
||||
OPENAI_TOKEN=sk-...
|
||||
DATABASE_PASSWORD=mypassword
|
||||
API_SECRET=secret123
|
||||
|
||||
# ✅ 대신 다음과 같은 네이밍 패턴을 사용하세요
|
||||
OPENAI_API_KEY=sk-...
|
||||
DATABASE_CREDENTIALS=mypassword
|
||||
API_CONFIG=secret123
|
||||
```
|
||||
|
||||
### 모범 사례
|
||||
|
||||
1. **표준 명명 규칙 사용**: `PROVIDER_TOKEN` 대신 `PROVIDER_API_KEY` 사용
|
||||
2. **먼저 로컬에서 테스트**: crew가 이름이 변경된 변수로 제대로 동작하는지 확인
|
||||
3. **코드 업데이트**: 이전 변수 이름을 참조하는 부분을 모두 변경
|
||||
4. **변경 내용 문서화**: 팀을 위해 이름이 변경된 변수를 기록
|
||||
|
||||
<Tip>
|
||||
배포 실패 시, 환경 변수 에러 메시지가 난해하다면 먼저 변수 이름이 이 패턴을
|
||||
따르는지 확인하세요.
|
||||
</Tip>
|
||||
|
||||
### 배포된 Crew와 상호작용하기
|
||||
|
||||
배포가 완료되면 다음을 통해 crew에 접근할 수 있습니다:
|
||||
|
||||
1. **REST API**: 플랫폼에서 아래의 주요 경로가 포함된 고유한 HTTPS 엔드포인트를 생성합니다:
|
||||
|
||||
- `/inputs`: 필요한 입력 파라미터 목록
|
||||
- `/kickoff`: 제공된 입력값으로 실행 시작
|
||||
- `/status/{kickoff_id}`: 실행 상태 확인
|
||||
|
||||
2. **웹 인터페이스**: [app.crewai.com](https://app.crewai.com)에 방문하여 다음을 확인할 수 있습니다:
|
||||
- **Status 탭**: 배포 정보, API 엔드포인트 세부 정보 및 인증 토큰 확인
|
||||
- **Run 탭**: crew 구조의 시각적 표현
|
||||
- **Executions 탭**: 모든 실행 내역
|
||||
- **Metrics 탭**: 성능 분석
|
||||
- **Traces 탭**: 상세 실행 인사이트
|
||||
|
||||
### 실행 트리거하기
|
||||
|
||||
Enterprise 대시보드에서 다음 작업을 수행할 수 있습니다:
|
||||
|
||||
1. crew 이름을 클릭하여 상세 정보를 엽니다
|
||||
2. 관리 인터페이스에서 "Trigger Crew"를 선택합니다
|
||||
3. 나타나는 모달에 필요한 입력값을 입력합니다
|
||||
4. 파이프라인을 따라 실행의 진행 상황을 모니터링합니다
|
||||
|
||||
### 모니터링 및 분석
|
||||
|
||||
Enterprise 플랫폼은 포괄적인 가시성 기능을 제공합니다:
|
||||
|
||||
- **실행 관리**: 활성 및 완료된 실행 추적
|
||||
- **트레이스**: 각 실행의 상세 분해
|
||||
- **메트릭**: 토큰 사용량, 실행 시간, 비용
|
||||
- **타임라인 보기**: 작업 시퀀스의 시각적 표현
|
||||
|
||||
### 고급 기능
|
||||
|
||||
Enterprise 플랫폼은 또한 다음을 제공합니다:
|
||||
|
||||
- **환경 변수 관리**: API 키를 안전하게 저장 및 관리
|
||||
- **LLM 연결**: 다양한 LLM 공급자와의 통합 구성
|
||||
- **Custom Tools Repository**: 도구 생성, 공유 및 설치
|
||||
- **Crew Studio**: 코드를 작성하지 않고 채팅 인터페이스를 통해 crew 빌드
|
||||
|
||||
<Card
|
||||
title="도움이 필요하신가요?"
|
||||
icon="headset"
|
||||
href="mailto:support@crewai.com"
|
||||
>
|
||||
Enterprise 플랫폼의 배포 문제 또는 문의 사항이 있으시면 지원팀에 연락해
|
||||
주십시오.
|
||||
</Card>
|
||||
438
docs/ko/enterprise/guides/deploy-to-amp.mdx
Normal file
@@ -0,0 +1,438 @@
|
||||
---
|
||||
title: "AMP에 배포하기"
|
||||
description: "Crew 또는 Flow를 CrewAI AMP에 배포하기"
|
||||
icon: "rocket"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
로컬에서 또는 Crew Studio를 통해 Crew나 Flow를 생성한 후, 다음 단계는 이를 CrewAI AMP
|
||||
플랫폼에 배포하는 것입니다. 본 가이드에서는 다양한 배포 방법을 다루며,
|
||||
여러분의 워크플로우에 가장 적합한 방식을 선택할 수 있도록 안내합니다.
|
||||
</Note>
|
||||
|
||||
## 사전 준비 사항
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="배포 준비가 완료된 프로젝트" icon="check-circle">
|
||||
로컬에서 성공적으로 실행되는 Crew 또는 Flow가 있어야 합니다.
|
||||
[배포 준비 가이드](/ko/enterprise/guides/prepare-for-deployment)를 따라 프로젝트 구조를 확인하세요.
|
||||
</Card>
|
||||
<Card title="GitHub 저장소" icon="github">
|
||||
코드가 GitHub 저장소에 있어야 합니다(GitHub 연동 방식의 경우).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Info>
|
||||
**Crews vs Flows**: 두 프로젝트 유형 모두 CrewAI AMP에서 "자동화"로 배포할 수 있습니다.
|
||||
배포 과정은 동일하지만, 프로젝트 구조가 다릅니다.
|
||||
자세한 내용은 [배포 준비하기](/ko/enterprise/guides/prepare-for-deployment)를 참조하세요.
|
||||
</Info>
|
||||
|
||||
## 옵션 1: CrewAI CLI를 사용한 배포
|
||||
|
||||
CLI는 로컬에서 개발된 Crew 또는 Flow를 AMP 플랫폼에 가장 빠르게 배포할 수 있는 방법을 제공합니다.
|
||||
CLI는 `pyproject.toml`에서 프로젝트 유형을 자동으로 감지하고 그에 맞게 빌드합니다.
|
||||
|
||||
<Steps>
|
||||
<Step title="CrewAI CLI 설치">
|
||||
아직 설치하지 않았다면 CrewAI CLI를 설치하세요:
|
||||
|
||||
```bash
|
||||
pip install crewai[tools]
|
||||
```
|
||||
|
||||
<Tip>
|
||||
CLI는 기본 CrewAI 패키지에 포함되어 있지만, `[tools]` 추가 옵션을 사용하면 모든 배포 종속성을 함께 설치할 수 있습니다.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Enterprise 플랫폼에 인증">
|
||||
먼저, CrewAI AMP 플랫폼에 CLI를 인증해야 합니다:
|
||||
|
||||
```bash
|
||||
# 이미 CrewAI AMP 계정이 있거나 새로 생성하고 싶을 때:
|
||||
crewai login
|
||||
```
|
||||
|
||||
위 명령어를 실행하면 CLI가 다음을 진행합니다:
|
||||
1. URL과 고유 기기 코드를 표시합니다
|
||||
2. 브라우저를 열어 인증 페이지로 이동합니다
|
||||
3. 기기 확인을 요청합니다
|
||||
4. 인증 과정을 완료합니다
|
||||
|
||||
인증이 성공적으로 완료되면 터미널에 확인 메시지가 표시됩니다!
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="배포 생성">
|
||||
|
||||
프로젝트 디렉터리에서 다음 명령어를 실행하세요:
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
```
|
||||
|
||||
이 명령어는 다음을 수행합니다:
|
||||
1. GitHub 저장소 정보를 감지합니다
|
||||
2. 로컬 `.env` 파일의 환경 변수를 식별합니다
|
||||
3. 이러한 변수를 Enterprise 플랫폼으로 안전하게 전송합니다
|
||||
4. 고유 식별자가 부여된 새 배포를 만듭니다
|
||||
|
||||
성공적으로 생성되면 다음과 같은 메시지가 표시됩니다:
|
||||
```shell
|
||||
Deployment created successfully!
|
||||
Name: your_project_name
|
||||
Deployment ID: 01234567-89ab-cdef-0123-456789abcdef
|
||||
Current Status: Deploy Enqueued
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="배포 진행 상황 모니터링">
|
||||
|
||||
다음 명령어로 배포 상태를 추적할 수 있습니다:
|
||||
|
||||
```bash
|
||||
crewai deploy status
|
||||
```
|
||||
|
||||
빌드 과정의 상세 로그가 필요하다면:
|
||||
|
||||
```bash
|
||||
crewai deploy logs
|
||||
```
|
||||
|
||||
<Tip>
|
||||
첫 배포는 컨테이너 이미지를 빌드하므로 일반적으로 10~15분 정도 소요됩니다. 이후 배포는 훨씬 빠릅니다.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 추가 CLI 명령어
|
||||
|
||||
CrewAI CLI는 배포를 관리하기 위한 여러 명령어를 제공합니다:
|
||||
|
||||
```bash
|
||||
# 모든 배포 목록 확인
|
||||
crewai deploy list
|
||||
|
||||
# 배포 상태 확인
|
||||
crewai deploy status
|
||||
|
||||
# 배포 로그 보기
|
||||
crewai deploy logs
|
||||
|
||||
# 코드 변경 후 업데이트 푸시
|
||||
crewai deploy push
|
||||
|
||||
# 배포 삭제
|
||||
crewai deploy remove <deployment_id>
|
||||
```
|
||||
|
||||
## 옵션 2: 웹 인터페이스를 통한 직접 배포
|
||||
|
||||
GitHub 계정을 연결하여 CrewAI AMP 웹 인터페이스를 통해 Crew 또는 Flow를 직접 배포할 수도 있습니다. 이 방법은 로컬 머신에서 CLI를 사용할 필요가 없습니다. 플랫폼은 자동으로 프로젝트 유형을 감지하고 적절하게 빌드를 처리합니다.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="GitHub로 푸시하기">
|
||||
|
||||
Crew를 GitHub 저장소에 푸시해야 합니다. 아직 Crew를 만들지 않았다면, [이 튜토리얼](/ko/quickstart)을 따라할 수 있습니다.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="GitHub를 CrewAI AMP에 연결하기">
|
||||
|
||||
1. [CrewAI AMP](https://app.crewai.com)에 로그인합니다.
|
||||
2. "Connect GitHub" 버튼을 클릭합니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="저장소 선택하기">
|
||||
|
||||
GitHub 계정을 연결한 후 배포할 저장소를 선택할 수 있습니다:
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="환경 변수 설정하기">
|
||||
|
||||
배포 전에, LLM 제공업체 또는 기타 서비스에 연결할 환경 변수를 설정해야 합니다:
|
||||
|
||||
1. 변수를 개별적으로 또는 일괄적으로 추가할 수 있습니다.
|
||||
2. 환경 변수는 `KEY=VALUE` 형식(한 줄에 하나씩)으로 입력합니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Crew 배포하기">
|
||||
|
||||
1. "Deploy" 버튼을 클릭하여 배포 프로세스를 시작합니다.
|
||||
2. 진행 바를 통해 진행 상황을 모니터링할 수 있습니다.
|
||||
3. 첫 번째 배포에는 일반적으로 약 10-15분 정도 소요되며, 이후 배포는 더 빠릅니다.
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
배포가 완료되면 다음을 확인할 수 있습니다:
|
||||
- Crew의 고유 URL
|
||||
- Crew API를 보호할 Bearer 토큰
|
||||
- 배포를 삭제해야 하는 경우 "Delete" 버튼
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## 옵션 3: API를 통한 재배포 (CI/CD 통합)
|
||||
|
||||
CI/CD 파이프라인에서 자동화된 배포를 위해 CrewAI API를 사용하여 기존 crew의 재배포를 트리거할 수 있습니다. 이 방법은 GitHub Actions, Jenkins 또는 기타 자동화 워크플로우에 특히 유용합니다.
|
||||
|
||||
<Steps>
|
||||
<Step title="개인 액세스 토큰 발급">
|
||||
|
||||
CrewAI AMP 계정 설정에서 API 토큰을 생성합니다:
|
||||
|
||||
1. [app.crewai.com](https://app.crewai.com)으로 이동합니다
|
||||
2. **Settings** → **Account** → **Personal Access Token**을 클릭합니다
|
||||
3. 새 토큰을 생성하고 안전하게 복사합니다
|
||||
4. 이 토큰을 CI/CD 시스템의 시크릿으로 저장합니다
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Automation UUID 찾기">
|
||||
|
||||
배포된 crew의 고유 식별자를 찾습니다:
|
||||
|
||||
1. CrewAI AMP 대시보드에서 **Automations**로 이동합니다
|
||||
2. 기존 automation/crew를 선택합니다
|
||||
3. **Additional Details**를 클릭합니다
|
||||
4. **UUID**를 복사합니다 - 이것이 특정 crew 배포를 식별합니다
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="API를 통한 재배포 트리거">
|
||||
|
||||
Deploy API 엔드포인트를 사용하여 재배포를 트리거합니다:
|
||||
|
||||
```bash
|
||||
curl -i -X POST \
|
||||
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
|
||||
https://app.crewai.com/crewai_plus/api/v1/crews/YOUR-AUTOMATION-UUID/deploy
|
||||
|
||||
# HTTP/2 200
|
||||
# content-type: application/json
|
||||
#
|
||||
# {
|
||||
# "uuid": "your-automation-uuid",
|
||||
# "status": "Deploy Enqueued",
|
||||
# "public_url": "https://your-crew-deployment.crewai.com",
|
||||
# "token": "your-bearer-token"
|
||||
# }
|
||||
```
|
||||
|
||||
<Info>
|
||||
Git에 연결되어 처음 생성된 automation의 경우, API가 재배포 전에 자동으로 저장소에서 최신 변경 사항을 가져옵니다.
|
||||
</Info>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="GitHub Actions 통합 예시">
|
||||
|
||||
더 복잡한 배포 트리거가 있는 GitHub Actions 워크플로우 예시입니다:
|
||||
|
||||
```yaml
|
||||
name: Deploy CrewAI Automation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
types: [ labeled ]
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy')) ||
|
||||
(github.event_name == 'release')
|
||||
steps:
|
||||
- name: Trigger CrewAI Redeployment
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer ${{ secrets.CREWAI_PAT }}" \
|
||||
https://app.crewai.com/crewai_plus/api/v1/crews/${{ secrets.CREWAI_AUTOMATION_UUID }}/deploy
|
||||
```
|
||||
|
||||
<Tip>
|
||||
`CREWAI_PAT`와 `CREWAI_AUTOMATION_UUID`를 저장소 시크릿으로 추가하세요. PR 배포의 경우 "deploy" 라벨을 추가하여 워크플로우를 트리거합니다.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## 배포된 Automation과 상호작용하기
|
||||
|
||||
배포가 완료되면 다음을 통해 crew에 접근할 수 있습니다:
|
||||
|
||||
1. **REST API**: 플랫폼에서 아래의 주요 경로가 포함된 고유한 HTTPS 엔드포인트를 생성합니다:
|
||||
|
||||
- `/inputs`: 필요한 입력 파라미터 목록
|
||||
- `/kickoff`: 제공된 입력값으로 실행 시작
|
||||
- `/status/{kickoff_id}`: 실행 상태 확인
|
||||
|
||||
2. **웹 인터페이스**: [app.crewai.com](https://app.crewai.com)에 방문하여 다음을 확인할 수 있습니다:
|
||||
- **Status 탭**: 배포 정보, API 엔드포인트 세부 정보 및 인증 토큰 확인
|
||||
- **Run 탭**: Crew 구조의 시각적 표현
|
||||
- **Executions 탭**: 모든 실행 내역
|
||||
- **Metrics 탭**: 성능 분석
|
||||
- **Traces 탭**: 상세 실행 인사이트
|
||||
|
||||
### 실행 트리거하기
|
||||
|
||||
Enterprise 대시보드에서 다음 작업을 수행할 수 있습니다:
|
||||
|
||||
1. Crew 이름을 클릭하여 상세 정보를 엽니다
|
||||
2. 관리 인터페이스에서 "Trigger Crew"를 선택합니다
|
||||
3. 나타나는 모달에 필요한 입력값을 입력합니다
|
||||
4. 파이프라인을 따라 실행의 진행 상황을 모니터링합니다
|
||||
|
||||
### 모니터링 및 분석
|
||||
|
||||
Enterprise 플랫폼은 포괄적인 가시성 기능을 제공합니다:
|
||||
|
||||
- **실행 관리**: 활성 및 완료된 실행 추적
|
||||
- **트레이스**: 각 실행의 상세 분해
|
||||
- **메트릭**: 토큰 사용량, 실행 시간, 비용
|
||||
- **타임라인 보기**: 작업 시퀀스의 시각적 표현
|
||||
|
||||
### 고급 기능
|
||||
|
||||
Enterprise 플랫폼은 또한 다음을 제공합니다:
|
||||
|
||||
- **환경 변수 관리**: API 키를 안전하게 저장 및 관리
|
||||
- **LLM 연결**: 다양한 LLM 공급자와의 통합 구성
|
||||
- **Custom Tools Repository**: 도구 생성, 공유 및 설치
|
||||
- **Crew Studio**: 코드를 작성하지 않고 채팅 인터페이스를 통해 crew 빌드
|
||||
|
||||
## 배포 실패 문제 해결
|
||||
|
||||
배포가 실패하면 다음과 같은 일반적인 문제를 확인하세요:
|
||||
|
||||
### 빌드 실패
|
||||
|
||||
#### uv.lock 파일 누락
|
||||
|
||||
**증상**: 의존성 해결 오류와 함께 빌드 초기에 실패
|
||||
|
||||
**해결책**: lock 파일을 생성하고 커밋합니다:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
<Warning>
|
||||
`uv.lock` 파일은 모든 배포에 필수입니다. 이 파일이 없으면 플랫폼에서
|
||||
의존성을 안정적으로 설치할 수 없습니다.
|
||||
</Warning>
|
||||
|
||||
#### 잘못된 프로젝트 구조
|
||||
|
||||
**증상**: "Could not find entry point" 또는 "Module not found" 오류
|
||||
|
||||
**해결책**: 프로젝트가 예상 구조와 일치하는지 확인합니다:
|
||||
|
||||
- **Crews와 Flows 모두**: 진입점이 `src/project_name/main.py`에 있어야 합니다
|
||||
- **Crews**: 진입점으로 `run()` 함수 사용
|
||||
- **Flows**: 진입점으로 `kickoff()` 함수 사용
|
||||
|
||||
자세한 구조 다이어그램은 [배포 준비하기](/ko/enterprise/guides/prepare-for-deployment)를 참조하세요.
|
||||
|
||||
#### CrewBase 데코레이터 누락
|
||||
|
||||
**증상**: "Crew not found", "Config not found" 또는 agent/task 구성 오류
|
||||
|
||||
**해결책**: **모든** crew 클래스가 `@CrewBase` 데코레이터를 사용하는지 확인합니다:
|
||||
|
||||
```python
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
|
||||
@CrewBase # 이 데코레이터는 필수입니다
|
||||
class YourCrew():
|
||||
"""Crew 설명"""
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# ... 나머지 crew 정의
|
||||
```
|
||||
|
||||
<Info>
|
||||
이것은 독립 실행형 Crews와 Flow 프로젝트 내에 포함된 crews 모두에 적용됩니다.
|
||||
모든 crew 클래스에 데코레이터가 필요합니다.
|
||||
</Info>
|
||||
|
||||
#### 잘못된 pyproject.toml 타입
|
||||
|
||||
**증상**: 빌드는 성공하지만 런타임에서 실패하거나 예상치 못한 동작
|
||||
|
||||
**해결책**: `[tool.crewai]` 섹션이 프로젝트 유형과 일치하는지 확인합니다:
|
||||
|
||||
```toml
|
||||
# Crew 프로젝트의 경우:
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
|
||||
# Flow 프로젝트의 경우:
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
|
||||
### 런타임 실패
|
||||
|
||||
#### LLM 연결 실패
|
||||
|
||||
**증상**: API 키 오류, "model not found" 또는 인증 실패
|
||||
|
||||
**해결책**:
|
||||
1. LLM 제공업체의 API 키가 환경 변수에 올바르게 설정되어 있는지 확인합니다
|
||||
2. 환경 변수 이름이 코드에서 예상하는 것과 일치하는지 확인합니다
|
||||
3. 배포 전에 동일한 환경 변수로 로컬에서 테스트합니다
|
||||
|
||||
#### Crew 실행 오류
|
||||
|
||||
**증상**: Crew가 시작되지만 실행 중에 실패
|
||||
|
||||
**해결책**:
|
||||
1. AMP 대시보드에서 실행 로그를 확인합니다 (Traces 탭)
|
||||
2. 모든 도구에 필요한 API 키가 구성되어 있는지 확인합니다
|
||||
3. `agents.yaml`의 agent 구성이 유효한지 확인합니다
|
||||
4. `tasks.yaml`의 task 구성에 구문 오류가 없는지 확인합니다
|
||||
|
||||
<Card title="도움이 필요하신가요?" icon="headset" href="mailto:support@crewai.com">
|
||||
배포 문제 또는 AMP 플랫폼에 대한 문의 사항이 있으시면 지원팀에 연락해 주세요.
|
||||
</Card>
|
||||
@@ -5,9 +5,54 @@ icon: "user-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
인간-중심(Human-In-The-Loop, HITL)은 인공지능과 인간 전문 지식을 결합하여 의사결정을 강화하고 작업 결과를 향상시키는 강력한 접근 방식입니다. 이 가이드는 CrewAI 내에서 HITL을 구현하는 방법을 보여줍니다.
|
||||
인간-중심(Human-In-The-Loop, HITL)은 인공지능과 인간 전문 지식을 결합하여 의사결정을 강화하고 작업 결과를 향상시키는 강력한 접근 방식입니다. 이 가이드는 CrewAI Enterprise 내에서 HITL을 구현하는 방법을 보여줍니다.
|
||||
|
||||
## HITL 워크플로 설정
|
||||
## CrewAI의 HITL 접근 방식
|
||||
|
||||
CrewAI는 human-in-the-loop 워크플로우를 구현하기 위한 두 가지 접근 방식을 제공합니다:
|
||||
|
||||
| 접근 방식 | 적합한 용도 | 버전 |
|
||||
|----------|----------|---------|
|
||||
| **Flow 기반** (`@human_feedback` 데코레이터) | Enterprise UI를 사용한 프로덕션, 이메일 우선 워크플로우, 전체 플랫폼 기능 | **1.8.0+** |
|
||||
| **Webhook 기반** | 커스텀 통합, 외부 시스템 (Slack, Teams 등), 레거시 설정 | 모든 버전 |
|
||||
|
||||
## Enterprise 플랫폼과 Flow 기반 HITL
|
||||
|
||||
<Note>
|
||||
`@human_feedback` 데코레이터는 **CrewAI 버전 1.8.0 이상**이 필요합니다.
|
||||
</Note>
|
||||
|
||||
Flow에서 `@human_feedback` 데코레이터를 사용하면, CrewAI Enterprise는 이메일 주소가 있는 누구나 검토 요청에 응답할 수 있는 **이메일 우선 HITL 시스템**을 제공합니다:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="이메일 우선 설계" icon="envelope">
|
||||
응답자가 이메일 알림을 받고 직접 회신할 수 있습니다—로그인이 필요 없습니다.
|
||||
</Card>
|
||||
<Card title="대시보드 검토" icon="desktop">
|
||||
원할 때 Enterprise 대시보드에서 HITL 요청을 검토하고 응답하세요.
|
||||
</Card>
|
||||
<Card title="유연한 라우팅" icon="route">
|
||||
메서드 패턴에 따라 특정 이메일로 요청을 라우팅하거나 Flow 상태에서 가져오세요.
|
||||
</Card>
|
||||
<Card title="자동 응답" icon="clock">
|
||||
타임아웃 내에 인간이 응답하지 않을 경우 자동 대체 응답을 구성하세요.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### 주요 이점
|
||||
|
||||
- **외부 응답자**: 플랫폼 사용자가 아니어도 이메일이 있는 누구나 응답 가능
|
||||
- **동적 할당**: Flow 상태에서 담당자 이메일 가져오기 (예: `account_owner_email`)
|
||||
- **간단한 구성**: 이메일 기반 라우팅은 사용자/역할 관리보다 설정이 쉬움
|
||||
- **배포 생성자 대체**: 라우팅 규칙이 일치하지 않으면 배포 생성자에게 알림
|
||||
|
||||
<Tip>
|
||||
`@human_feedback` 데코레이터의 구현 세부 사항은 [Flow에서 인간 피드백](/ko/learn/human-feedback-in-flows) 가이드를 참조하세요.
|
||||
</Tip>
|
||||
|
||||
## Webhook 기반 HITL 워크플로 설정
|
||||
|
||||
Slack, Microsoft Teams 또는 자체 애플리케이션과 같은 외부 시스템과의 커스텀 통합을 위해 webhook 기반 접근 방식을 사용할 수 있습니다:
|
||||
|
||||
<Steps>
|
||||
<Step title="작업 구성">
|
||||
@@ -99,3 +144,14 @@ HITL 워크플로우는 특히 다음과 같은 경우에 유용합니다:
|
||||
- 민감하거나 위험도가 높은 작업
|
||||
- 인간의 판단이 필요한 창의적 작업
|
||||
- 준수 및 규제 검토
|
||||
|
||||
## 자세히 알아보기
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Flow HITL 관리" icon="users-gear" href="/ko/enterprise/features/flow-hitl-management">
|
||||
이메일 알림, 라우팅 규칙, 자동 응답 및 분석을 포함한 전체 Enterprise Flow HITL 플랫폼 기능을 살펴보세요.
|
||||
</Card>
|
||||
<Card title="Flow에서 인간 피드백" icon="code" href="/ko/learn/human-feedback-in-flows">
|
||||
Flow에서 `@human_feedback` 데코레이터 구현 가이드.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
305
docs/ko/enterprise/guides/prepare-for-deployment.mdx
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
title: "배포 준비하기"
|
||||
description: "Crew 또는 Flow가 CrewAI AMP에 배포될 준비가 되었는지 확인하기"
|
||||
icon: "clipboard-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
CrewAI AMP에 배포하기 전에, 프로젝트가 올바르게 구성되어 있는지 확인하는 것이 중요합니다.
|
||||
Crews와 Flows 모두 "자동화"로 배포할 수 있지만, 성공적인 배포를 위해 충족해야 하는
|
||||
서로 다른 프로젝트 구조와 요구 사항이 있습니다.
|
||||
</Note>
|
||||
|
||||
## 자동화 이해하기
|
||||
|
||||
CrewAI AMP에서 **자동화(automations)**는 배포 가능한 Agentic AI 프로젝트의 총칭입니다. 자동화는 다음 중 하나일 수 있습니다:
|
||||
|
||||
- **Crew**: 작업을 함께 수행하는 AI 에이전트들의 독립 실행형 팀
|
||||
- **Flow**: 여러 crew, 직접 LLM 호출 및 절차적 로직을 결합할 수 있는 오케스트레이션된 워크플로우
|
||||
|
||||
배포하는 유형을 이해하는 것은 프로젝트 구조와 진입점이 다르기 때문에 필수적입니다.
|
||||
|
||||
## Crews vs Flows: 주요 차이점
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Crew 프로젝트" icon="users">
|
||||
에이전트와 작업을 정의하는 `crew.py`가 있는 독립 실행형 AI 에이전트 팀. 집중적이고 협업적인 작업에 적합합니다.
|
||||
</Card>
|
||||
<Card title="Flow 프로젝트" icon="diagram-project">
|
||||
`crews/` 폴더에 포함된 crew가 있는 오케스트레이션된 워크플로우. 복잡한 다단계 프로세스에 적합합니다.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| 측면 | Crew | Flow |
|
||||
|------|------|------|
|
||||
| **프로젝트 구조** | `crew.py`가 있는 `src/project_name/` | `crews/` 폴더가 있는 `src/project_name/` |
|
||||
| **메인 로직 위치** | `src/project_name/crew.py` | `src/project_name/main.py` (Flow 클래스) |
|
||||
| **진입점 함수** | `main.py`의 `run()` | `main.py`의 `kickoff()` |
|
||||
| **pyproject.toml 타입** | `type = "crew"` | `type = "flow"` |
|
||||
| **CLI 생성 명령어** | `crewai create crew name` | `crewai create flow name` |
|
||||
| **설정 위치** | `src/project_name/config/` | `src/project_name/crews/crew_name/config/` |
|
||||
| **다른 crew 포함 가능** | 아니오 | 예 (`crews/` 폴더 내) |
|
||||
|
||||
## 프로젝트 구조 참조
|
||||
|
||||
### Crew 프로젝트 구조
|
||||
|
||||
`crewai create crew my_crew`를 실행하면 다음 구조를 얻습니다:
|
||||
|
||||
```
|
||||
my_crew/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # type = "crew"여야 함
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # 배포에 필수
|
||||
└── src/
|
||||
└── my_crew/
|
||||
├── __init__.py
|
||||
├── main.py # run() 함수가 있는 진입점
|
||||
├── crew.py # @CrewBase 데코레이터가 있는 Crew 클래스
|
||||
├── tools/
|
||||
│ ├── custom_tool.py
|
||||
│ └── __init__.py
|
||||
└── config/
|
||||
├── agents.yaml # 에이전트 정의
|
||||
└── tasks.yaml # 작업 정의
|
||||
```
|
||||
|
||||
<Warning>
|
||||
중첩된 `src/project_name/` 구조는 Crews에 매우 중요합니다.
|
||||
잘못된 레벨에 파일을 배치하면 배포 실패의 원인이 됩니다.
|
||||
</Warning>
|
||||
|
||||
### Flow 프로젝트 구조
|
||||
|
||||
`crewai create flow my_flow`를 실행하면 다음 구조를 얻습니다:
|
||||
|
||||
```
|
||||
my_flow/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # type = "flow"여야 함
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # 배포에 필수
|
||||
└── src/
|
||||
└── my_flow/
|
||||
├── __init__.py
|
||||
├── main.py # kickoff() 함수 + Flow 클래스가 있는 진입점
|
||||
├── crews/ # 포함된 crews 폴더
|
||||
│ └── poem_crew/
|
||||
│ ├── __init__.py
|
||||
│ ├── poem_crew.py # @CrewBase 데코레이터가 있는 Crew
|
||||
│ └── config/
|
||||
│ ├── agents.yaml
|
||||
│ └── tasks.yaml
|
||||
└── tools/
|
||||
├── __init__.py
|
||||
└── custom_tool.py
|
||||
```
|
||||
|
||||
<Info>
|
||||
Crews와 Flows 모두 `src/project_name/` 구조를 사용합니다.
|
||||
핵심 차이점은 Flows는 포함된 crews를 위한 `crews/` 폴더가 있고,
|
||||
Crews는 프로젝트 폴더에 직접 `crew.py`가 있다는 것입니다.
|
||||
</Info>
|
||||
|
||||
## 배포 전 체크리스트
|
||||
|
||||
이 체크리스트를 사용하여 프로젝트가 배포 준비가 되었는지 확인하세요.
|
||||
|
||||
### 1. pyproject.toml 설정 확인
|
||||
|
||||
`pyproject.toml`에 올바른 `[tool.crewai]` 섹션이 포함되어야 합니다:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Crews의 경우">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Flows의 경우">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
`type`이 프로젝트 구조와 일치하지 않으면 빌드가 실패하거나
|
||||
자동화가 올바르게 실행되지 않습니다.
|
||||
</Warning>
|
||||
|
||||
### 2. uv.lock 파일 존재 확인
|
||||
|
||||
CrewAI는 의존성 관리를 위해 `uv`를 사용합니다. `uv.lock` 파일은 재현 가능한 빌드를 보장하며 배포에 **필수**입니다.
|
||||
|
||||
```bash
|
||||
# lock 파일 생성 또는 업데이트
|
||||
uv lock
|
||||
|
||||
# 존재 여부 확인
|
||||
ls -la uv.lock
|
||||
```
|
||||
|
||||
파일이 존재하지 않으면 `uv lock`을 실행하고 저장소에 커밋하세요:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
### 3. CrewBase 데코레이터 사용 확인
|
||||
|
||||
**모든 crew 클래스는 `@CrewBase` 데코레이터를 사용해야 합니다.** 이것은 다음에 적용됩니다:
|
||||
|
||||
- 독립 실행형 crew 프로젝트
|
||||
- Flow 프로젝트 내에 포함된 crews
|
||||
|
||||
```python
|
||||
from crewai import Agent, Crew, Process, Task
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from typing import List
|
||||
|
||||
@CrewBase # 이 데코레이터는 필수입니다
|
||||
class MyCrew():
|
||||
"""내 crew 설명"""
|
||||
|
||||
agents: List[BaseAgent]
|
||||
tasks: List[Task]
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
@task
|
||||
def my_task(self) -> Task:
|
||||
return Task(
|
||||
config=self.tasks_config['my_task'] # type: ignore[index]
|
||||
)
|
||||
|
||||
@crew
|
||||
def crew(self) -> Crew:
|
||||
return Crew(
|
||||
agents=self.agents,
|
||||
tasks=self.tasks,
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
)
|
||||
```
|
||||
|
||||
<Warning>
|
||||
`@CrewBase` 데코레이터를 잊으면 에이전트나 작업 구성이 누락되었다는
|
||||
오류와 함께 배포가 실패합니다.
|
||||
</Warning>
|
||||
|
||||
### 4. 프로젝트 진입점 확인
|
||||
|
||||
Crews와 Flows 모두 `src/project_name/main.py`에 진입점이 있습니다:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Crews의 경우">
|
||||
진입점은 `run()` 함수를 사용합니다:
|
||||
|
||||
```python
|
||||
# src/my_crew/main.py
|
||||
from my_crew.crew import MyCrew
|
||||
|
||||
def run():
|
||||
"""crew를 실행합니다."""
|
||||
inputs = {'topic': 'AI in Healthcare'}
|
||||
result = MyCrew().crew().kickoff(inputs=inputs)
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Flows의 경우">
|
||||
진입점은 Flow 클래스와 함께 `kickoff()` 함수를 사용합니다:
|
||||
|
||||
```python
|
||||
# src/my_flow/main.py
|
||||
from crewai.flow import Flow, listen, start
|
||||
from my_flow.crews.poem_crew.poem_crew import PoemCrew
|
||||
|
||||
class MyFlow(Flow):
|
||||
@start()
|
||||
def begin(self):
|
||||
# Flow 로직
|
||||
result = PoemCrew().crew().kickoff(inputs={...})
|
||||
return result
|
||||
|
||||
def kickoff():
|
||||
"""flow를 실행합니다."""
|
||||
MyFlow().kickoff()
|
||||
|
||||
if __name__ == "__main__":
|
||||
kickoff()
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 5. 환경 변수 준비
|
||||
|
||||
배포 전에 다음을 준비해야 합니다:
|
||||
|
||||
1. **LLM API 키** (OpenAI, Anthropic, Google 등)
|
||||
2. **도구 API 키** - 외부 도구를 사용하는 경우 (Serper 등)
|
||||
|
||||
<Tip>
|
||||
구성 문제를 조기에 발견하기 위해 배포 전에 동일한 환경 변수로
|
||||
로컬에서 프로젝트를 테스트하세요.
|
||||
</Tip>
|
||||
|
||||
## 빠른 검증 명령어
|
||||
|
||||
프로젝트 루트에서 다음 명령어를 실행하여 설정을 빠르게 확인하세요:
|
||||
|
||||
```bash
|
||||
# 1. pyproject.toml에서 프로젝트 타입 확인
|
||||
grep -A2 "\[tool.crewai\]" pyproject.toml
|
||||
|
||||
# 2. uv.lock 존재 확인
|
||||
ls -la uv.lock || echo "오류: uv.lock이 없습니다! 'uv lock'을 실행하세요"
|
||||
|
||||
# 3. src/ 구조 존재 확인
|
||||
ls -la src/*/main.py 2>/dev/null || echo "src/에서 main.py를 찾을 수 없습니다"
|
||||
|
||||
# 4. Crews의 경우 - crew.py 존재 확인
|
||||
ls -la src/*/crew.py 2>/dev/null || echo "crew.py가 없습니다 (Crews에서 예상됨)"
|
||||
|
||||
# 5. Flows의 경우 - crews/ 폴더 존재 확인
|
||||
ls -la src/*/crews/ 2>/dev/null || echo "crews/ 폴더가 없습니다 (Flows에서 예상됨)"
|
||||
|
||||
# 6. CrewBase 사용 확인
|
||||
grep -r "@CrewBase" . --include="*.py"
|
||||
```
|
||||
|
||||
## 일반적인 설정 실수
|
||||
|
||||
| 실수 | 증상 | 해결 방법 |
|
||||
|------|------|----------|
|
||||
| `uv.lock` 누락 | 의존성 해결 중 빌드 실패 | `uv lock` 실행 후 커밋 |
|
||||
| pyproject.toml의 잘못된 `type` | 빌드 성공하지만 런타임 실패 | 올바른 타입으로 변경 |
|
||||
| `@CrewBase` 데코레이터 누락 | "Config not found" 오류 | 모든 crew 클래스에 데코레이터 추가 |
|
||||
| `src/` 대신 루트에 파일 배치 | 진입점을 찾을 수 없음 | `src/project_name/`으로 이동 |
|
||||
| `run()` 또는 `kickoff()` 누락 | 자동화를 시작할 수 없음 | 올바른 진입 함수 추가 |
|
||||
|
||||
## 다음 단계
|
||||
|
||||
프로젝트가 모든 체크리스트 항목을 통과하면 배포할 준비가 된 것입니다:
|
||||
|
||||
<Card title="AMP에 배포하기" icon="rocket" href="/ko/enterprise/guides/deploy-to-amp">
|
||||
CLI, 웹 인터페이스 또는 CI/CD 통합을 사용하여 Crew 또는 Flow를 CrewAI AMP에
|
||||
배포하려면 배포 가이드를 따르세요.
|
||||
</Card>
|
||||
@@ -200,6 +200,25 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `clientData` (array, 선택사항): 클라이언트별 데이터. 각 항목은 `key` (string)와 `value` (string)가 있는 객체.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/update_contact_group">
|
||||
**설명:** 연락처 그룹의 정보를 업데이트합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `resourceName` (string, 필수): 연락처 그룹의 리소스 이름 (예: 'contactGroups/myContactGroup').
|
||||
- `name` (string, 필수): 연락처 그룹의 이름.
|
||||
- `clientData` (array, 선택사항): 클라이언트별 데이터. 각 항목은 `key` (string)와 `value` (string)가 있는 객체.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/delete_contact_group">
|
||||
**설명:** 연락처 그룹을 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `resourceName` (string, 필수): 삭제할 연락처 그룹의 리소스 이름 (예: 'contactGroups/myContactGroup').
|
||||
- `deleteContacts` (boolean, 선택사항): 그룹 내 연락처도 삭제할지 여부. 기본값: false
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
|
||||
@@ -131,6 +131,297 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `endIndex` (integer, 필수): 범위의 끝 인덱스.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_document_with_content">
|
||||
**설명:** 내용이 포함된 새 Google 문서를 한 번에 만듭니다.
|
||||
|
||||
**매개변수:**
|
||||
- `title` (string, 필수): 새 문서의 제목. 문서 상단과 Google Drive에 표시됩니다.
|
||||
- `content` (string, 선택사항): 문서에 삽입할 텍스트 내용. 새 단락에는 `\n`을 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/append_text">
|
||||
**설명:** Google 문서의 끝에 텍스트를 추가합니다. 인덱스를 지정할 필요 없이 자동으로 문서 끝에 삽입됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): create_document 응답 또는 URL에서 가져온 문서 ID.
|
||||
- `text` (string, 필수): 문서 끝에 추가할 텍스트. 새 단락에는 `\n`을 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_bold">
|
||||
**설명:** Google 문서에서 텍스트를 굵게 만들거나 굵게 서식을 제거합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `bold` (boolean, 필수): 굵게 만들려면 `true`, 굵게를 제거하려면 `false`로 설정.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_italic">
|
||||
**설명:** Google 문서에서 텍스트를 기울임꼴로 만들거나 기울임꼴 서식을 제거합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `italic` (boolean, 필수): 기울임꼴로 만들려면 `true`, 기울임꼴을 제거하려면 `false`로 설정.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_underline">
|
||||
**설명:** Google 문서에서 텍스트에 밑줄 서식을 추가하거나 제거합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `underline` (boolean, 필수): 밑줄을 추가하려면 `true`, 밑줄을 제거하려면 `false`로 설정.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_strikethrough">
|
||||
**설명:** Google 문서에서 텍스트에 취소선 서식을 추가하거나 제거합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `strikethrough` (boolean, 필수): 취소선을 추가하려면 `true`, 제거하려면 `false`로 설정.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_font_size">
|
||||
**설명:** Google 문서에서 텍스트의 글꼴 크기를 변경합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `fontSize` (number, 필수): 포인트 단위의 글꼴 크기. 일반적인 크기: 10, 11, 12, 14, 16, 18, 24, 36.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_color">
|
||||
**설명:** Google 문서에서 RGB 값(0-1 스케일)을 사용하여 텍스트 색상을 변경합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 서식을 지정할 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 서식을 지정할 텍스트의 끝 위치 (배타적).
|
||||
- `red` (number, 필수): 빨강 구성 요소 (0-1). 예: `1`은 완전한 빨강.
|
||||
- `green` (number, 필수): 초록 구성 요소 (0-1). 예: `0.5`는 절반 초록.
|
||||
- `blue` (number, 필수): 파랑 구성 요소 (0-1). 예: `0`은 파랑 없음.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_hyperlink">
|
||||
**설명:** Google 문서에서 기존 텍스트를 클릭 가능한 하이퍼링크로 변환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 링크로 만들 텍스트의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 링크로 만들 텍스트의 끝 위치 (배타적).
|
||||
- `url` (string, 필수): 링크가 가리킬 URL. 예: `"https://example.com"`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/apply_heading_style">
|
||||
**설명:** Google 문서에서 텍스트 범위에 제목 또는 단락 스타일을 적용합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 스타일을 적용할 단락의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 스타일을 적용할 단락의 끝 위치.
|
||||
- `style` (string, 필수): 적용할 스타일. 옵션: `NORMAL_TEXT`, `TITLE`, `SUBTITLE`, `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_paragraph_alignment">
|
||||
**설명:** Google 문서에서 단락의 텍스트 정렬을 설정합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 정렬할 단락의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 정렬할 단락의 끝 위치.
|
||||
- `alignment` (string, 필수): 텍스트 정렬. 옵션: `START` (왼쪽), `CENTER`, `END` (오른쪽), `JUSTIFIED`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_line_spacing">
|
||||
**설명:** Google 문서에서 단락의 줄 간격을 설정합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 단락의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 단락의 끝 위치.
|
||||
- `lineSpacing` (number, 필수): 백분율로 나타낸 줄 간격. `100` = 단일, `115` = 1.15배, `150` = 1.5배, `200` = 이중.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_paragraph_bullets">
|
||||
**설명:** Google 문서에서 단락을 글머리 기호 또는 번호 매기기 목록으로 변환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 목록으로 변환할 단락의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 목록으로 변환할 단락의 끝 위치.
|
||||
- `bulletPreset` (string, 필수): 글머리 기호/번호 매기기 스타일. 옵션: `BULLET_DISC_CIRCLE_SQUARE`, `BULLET_DIAMONDX_ARROW3D_SQUARE`, `BULLET_CHECKBOX`, `BULLET_ARROW_DIAMOND_DISC`, `BULLET_STAR_CIRCLE_SQUARE`, `NUMBERED_DECIMAL_ALPHA_ROMAN`, `NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS`, `NUMBERED_DECIMAL_NESTED`, `NUMBERED_UPPERALPHA_ALPHA_ROMAN`, `NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_paragraph_bullets">
|
||||
**설명:** Google 문서에서 단락의 글머리 기호 또는 번호 매기기를 제거합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `startIndex` (integer, 필수): 목록 단락의 시작 위치.
|
||||
- `endIndex` (integer, 필수): 목록 단락의 끝 위치.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_with_content">
|
||||
**설명:** Google 문서에 내용이 포함된 표를 한 번에 삽입합니다. 내용은 2D 배열로 제공하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `rows` (integer, 필수): 표의 행 수.
|
||||
- `columns` (integer, 필수): 표의 열 수.
|
||||
- `index` (integer, 선택사항): 표를 삽입할 위치. 제공하지 않으면 문서 끝에 삽입됩니다.
|
||||
- `content` (array, 필수): 2D 배열로 된 표 내용. 각 내부 배열은 행입니다. 예: `[["Year", "Revenue"], ["2023", "$43B"], ["2024", "$45B"]]`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_row">
|
||||
**설명:** 기존 표의 참조 셀 위 또는 아래에 새 행을 삽입합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스. get_document에서 가져오세요.
|
||||
- `rowIndex` (integer, 필수): 참조 셀의 행 인덱스 (0 기반).
|
||||
- `columnIndex` (integer, 선택사항): 참조 셀의 열 인덱스 (0 기반). 기본값: `0`.
|
||||
- `insertBelow` (boolean, 선택사항): `true`이면 참조 행 아래에, `false`이면 위에 삽입. 기본값: `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_column">
|
||||
**설명:** 기존 표의 참조 셀 왼쪽 또는 오른쪽에 새 열을 삽입합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스.
|
||||
- `rowIndex` (integer, 선택사항): 참조 셀의 행 인덱스 (0 기반). 기본값: `0`.
|
||||
- `columnIndex` (integer, 필수): 참조 셀의 열 인덱스 (0 기반).
|
||||
- `insertRight` (boolean, 선택사항): `true`이면 오른쪽에, `false`이면 왼쪽에 삽입. 기본값: `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_row">
|
||||
**설명:** Google 문서의 기존 표에서 행을 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스.
|
||||
- `rowIndex` (integer, 필수): 삭제할 행 인덱스 (0 기반).
|
||||
- `columnIndex` (integer, 선택사항): 행의 아무 셀의 열 인덱스 (0 기반). 기본값: `0`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_column">
|
||||
**설명:** Google 문서의 기존 표에서 열을 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스.
|
||||
- `rowIndex` (integer, 선택사항): 열의 아무 셀의 행 인덱스 (0 기반). 기본값: `0`.
|
||||
- `columnIndex` (integer, 필수): 삭제할 열 인덱스 (0 기반).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/merge_table_cells">
|
||||
**설명:** 표 셀 범위를 단일 셀로 병합합니다. 모든 셀의 내용이 보존됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스.
|
||||
- `rowIndex` (integer, 필수): 병합의 시작 행 인덱스 (0 기반).
|
||||
- `columnIndex` (integer, 필수): 병합의 시작 열 인덱스 (0 기반).
|
||||
- `rowSpan` (integer, 필수): 병합할 행 수.
|
||||
- `columnSpan` (integer, 필수): 병합할 열 수.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/unmerge_table_cells">
|
||||
**설명:** 이전에 병합된 표 셀을 개별 셀로 분리합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `tableStartIndex` (integer, 필수): 표의 시작 인덱스.
|
||||
- `rowIndex` (integer, 필수): 병합된 셀의 행 인덱스 (0 기반).
|
||||
- `columnIndex` (integer, 필수): 병합된 셀의 열 인덱스 (0 기반).
|
||||
- `rowSpan` (integer, 필수): 병합된 셀이 차지하는 행 수.
|
||||
- `columnSpan` (integer, 필수): 병합된 셀이 차지하는 열 수.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_inline_image">
|
||||
**설명:** 공개 URL에서 Google 문서에 이미지를 삽입합니다. 이미지는 공개적으로 접근 가능해야 하고, 50MB 미만이며, PNG/JPEG/GIF 형식이어야 합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `uri` (string, 필수): 이미지의 공개 URL. 인증 없이 접근 가능해야 합니다.
|
||||
- `index` (integer, 선택사항): 이미지를 삽입할 위치. 제공하지 않으면 문서 끝에 삽입됩니다. 기본값: `1`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_section_break">
|
||||
**설명:** 서로 다른 서식을 가진 문서 섹션을 만들기 위해 섹션 나누기를 삽입합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `index` (integer, 필수): 섹션 나누기를 삽입할 위치.
|
||||
- `sectionType` (string, 필수): 섹션 나누기의 유형. 옵션: `CONTINUOUS` (같은 페이지에 유지), `NEXT_PAGE` (새 페이지 시작).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_header">
|
||||
**설명:** 문서의 머리글을 만듭니다. insert_text를 사용하여 머리글 내용을 추가할 수 있는 headerId를 반환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `type` (string, 선택사항): 머리글 유형. 옵션: `DEFAULT`. 기본값: `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_footer">
|
||||
**설명:** 문서의 바닥글을 만듭니다. insert_text를 사용하여 바닥글 내용을 추가할 수 있는 footerId를 반환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `type` (string, 선택사항): 바닥글 유형. 옵션: `DEFAULT`. 기본값: `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_header">
|
||||
**설명:** 문서에서 머리글을 삭제합니다. headerId를 찾으려면 get_document를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `headerId` (string, 필수): 삭제할 머리글 ID. get_document 응답에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_footer">
|
||||
**설명:** 문서에서 바닥글을 삭제합니다. footerId를 찾으려면 get_document를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `documentId` (string, 필수): 문서 ID.
|
||||
- `footerId` (string, 필수): 삭제할 바닥글 ID. get_document 응답에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
|
||||
@@ -61,6 +61,22 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_metadata">
|
||||
**설명:** 프레젠테이션에 대한 가벼운 메타데이터(제목, 슬라이드 수, 슬라이드 ID)를 가져옵니다. 전체 콘텐츠를 가져오기 전에 먼저 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 검색할 프레젠테이션의 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_text">
|
||||
**설명:** 프레젠테이션에서 모든 텍스트 콘텐츠를 추출합니다. 슬라이드 ID와 도형 및 테이블의 텍스트만 반환합니다 (포맷팅 없음).
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation">
|
||||
**설명:** ID로 프레젠테이션을 검색합니다.
|
||||
|
||||
@@ -80,6 +96,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_slide_text">
|
||||
**설명:** 단일 슬라이드에서 텍스트 콘텐츠를 추출합니다. 도형 및 테이블의 텍스트만 반환합니다 (포맷팅 또는 스타일 없음).
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `pageObjectId` (string, 필수): 텍스트를 가져올 슬라이드/페이지의 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_page">
|
||||
**설명:** ID로 특정 페이지를 검색합니다.
|
||||
|
||||
@@ -98,6 +123,120 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide">
|
||||
**설명:** 프레젠테이션에 추가 빈 슬라이드를 추가합니다. 새 프레젠테이션에는 이미 빈 슬라이드가 하나 있습니다. 먼저 get_presentation_metadata를 확인하세요. 제목/본문 영역이 있는 슬라이드는 create_slide_with_layout을 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `insertionIndex` (integer, 선택사항): 슬라이드를 삽입할 위치 (0 기반). 생략하면 맨 끝에 추가됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide_with_layout">
|
||||
**설명:** 제목, 본문 등의 플레이스홀더 영역이 있는 미리 정의된 레이아웃으로 슬라이드를 만듭니다. 구조화된 콘텐츠에는 create_slide보다 적합합니다. 생성 후 get_page로 플레이스홀더 ID를 찾고, 그 안에 텍스트를 삽입하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `layout` (string, 필수): 레이아웃 유형. 옵션: `BLANK`, `TITLE`, `TITLE_AND_BODY`, `TITLE_AND_TWO_COLUMNS`, `TITLE_ONLY`, `SECTION_HEADER`, `ONE_COLUMN_TEXT`, `MAIN_POINT`, `BIG_NUMBER`. 제목+설명은 TITLE_AND_BODY, 제목만은 TITLE, 섹션 구분은 SECTION_HEADER가 적합합니다.
|
||||
- `insertionIndex` (integer, 선택사항): 삽입할 위치 (0 기반). 생략하면 맨 끝에 추가됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_text_box">
|
||||
**설명:** 콘텐츠가 있는 텍스트 상자를 슬라이드에 만듭니다. 제목, 설명, 단락에 사용합니다. 테이블에는 사용하지 마세요. 선택적으로 EMU 단위로 위치(x, y)와 크기(width, height)를 지정할 수 있습니다 (914400 EMU = 1 인치).
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 텍스트 상자를 추가할 슬라이드의 ID.
|
||||
- `text` (string, 필수): 텍스트 상자의 텍스트 내용.
|
||||
- `x` (integer, 선택사항): EMU 단위 X 위치 (914400 = 1 인치). 기본값: 914400 (왼쪽에서 1 인치).
|
||||
- `y` (integer, 선택사항): EMU 단위 Y 위치 (914400 = 1 인치). 기본값: 914400 (위에서 1 인치).
|
||||
- `width` (integer, 선택사항): EMU 단위 너비. 기본값: 7315200 (약 8 인치).
|
||||
- `height` (integer, 선택사항): EMU 단위 높이. 기본값: 914400 (약 1 인치).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/delete_slide">
|
||||
**설명:** 프레젠테이션에서 슬라이드를 제거합니다. 슬라이드 ID를 찾으려면 먼저 get_presentation을 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 삭제할 슬라이드의 객체 ID. get_presentation에서 가져옵니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/duplicate_slide">
|
||||
**설명:** 기존 슬라이드의 복사본을 만듭니다. 복사본은 원본 바로 다음에 삽입됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 복제할 슬라이드의 객체 ID. get_presentation에서 가져옵니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/move_slides">
|
||||
**설명:** 슬라이드를 새 위치로 이동하여 순서를 변경합니다. 슬라이드 ID는 현재 프레젠테이션 순서대로 있어야 합니다 (중복 없음).
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideIds` (string 배열, 필수): 이동할 슬라이드 ID 배열. 현재 프레젠테이션 순서대로 있어야 합니다.
|
||||
- `insertionIndex` (integer, 필수): 대상 위치 (0 기반). 0 = 맨 앞, 슬라이드 수 = 맨 끝.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_youtube_video">
|
||||
**설명:** 슬라이드에 YouTube 동영상을 삽입합니다. 동영상 ID는 YouTube URL의 "v=" 다음 값입니다 (예: youtube.com/watch?v=abc123의 경우 "abc123" 사용).
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 동영상을 추가할 슬라이드의 ID. get_presentation에서 가져옵니다.
|
||||
- `videoId` (string, 필수): YouTube 동영상 ID (URL의 v= 다음 값).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_drive_video">
|
||||
**설명:** 슬라이드에 Google Drive의 동영상을 삽입합니다. 파일 ID는 Drive 파일 URL에서 찾을 수 있습니다.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 동영상을 추가할 슬라이드의 ID. get_presentation에서 가져옵니다.
|
||||
- `fileId` (string, 필수): 동영상의 Google Drive 파일 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/set_slide_background_image">
|
||||
**설명:** 슬라이드의 배경 이미지를 설정합니다. 이미지 URL은 공개적으로 액세스 가능해야 합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 배경을 설정할 슬라이드의 ID. get_presentation에서 가져옵니다.
|
||||
- `imageUrl` (string, 필수): 배경으로 사용할 이미지의 공개적으로 액세스 가능한 URL.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table">
|
||||
**설명:** 슬라이드에 빈 테이블을 만듭니다. 콘텐츠가 있는 테이블을 만들려면 create_table_with_content를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 테이블을 추가할 슬라이드의 ID. get_presentation에서 가져옵니다.
|
||||
- `rows` (integer, 필수): 테이블의 행 수.
|
||||
- `columns` (integer, 필수): 테이블의 열 수.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table_with_content">
|
||||
**설명:** 한 번의 작업으로 콘텐츠가 있는 테이블을 만듭니다. 콘텐츠는 2D 배열로 제공하며, 각 내부 배열은 행을 나타냅니다. 예: [["Header1", "Header2"], ["Row1Col1", "Row1Col2"]].
|
||||
|
||||
**매개변수:**
|
||||
- `presentationId` (string, 필수): 프레젠테이션의 ID.
|
||||
- `slideId` (string, 필수): 테이블을 추가할 슬라이드의 ID. get_presentation에서 가져옵니다.
|
||||
- `rows` (integer, 필수): 테이블의 행 수.
|
||||
- `columns` (integer, 필수): 테이블의 열 수.
|
||||
- `content` (array, 필수): 2D 배열 형태의 테이블 콘텐츠. 각 내부 배열은 행입니다. 예: [["Year", "Revenue"], ["2023", "$10M"]].
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/import_data_from_sheet">
|
||||
**설명:** Google 시트에서 프레젠테이션으로 데이터를 가져옵니다.
|
||||
|
||||
|
||||
@@ -148,6 +148,16 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_table_data">
|
||||
**설명:** Excel 워크시트의 특정 테이블에서 데이터를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_id` (string, 필수): Excel 파일의 ID.
|
||||
- `worksheet_name` (string, 필수): 워크시트의 이름.
|
||||
- `table_name` (string, 필수): 테이블의 이름.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/create_chart">
|
||||
**설명:** Excel 워크시트에 차트를 만듭니다.
|
||||
|
||||
@@ -180,6 +190,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_used_range_metadata">
|
||||
**설명:** Excel 워크시트의 사용된 범위 메타데이터(크기만, 데이터 없음)를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_id` (string, 필수): Excel 파일의 ID.
|
||||
- `worksheet_name` (string, 필수): 워크시트의 이름.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/list_charts">
|
||||
**설명:** Excel 워크시트의 모든 차트를 가져옵니다.
|
||||
|
||||
|
||||
@@ -150,6 +150,49 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `item_id` (string, 필수): 파일의 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/list_files_by_path">
|
||||
**설명:** 특정 OneDrive 경로의 파일과 폴더를 나열합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `folder_path` (string, 필수): 폴더 경로 (예: 'Documents/Reports').
|
||||
- `top` (integer, 선택사항): 검색할 항목 수 (최대 1000). 기본값: 50.
|
||||
- `orderby` (string, 선택사항): 필드별 정렬 (예: "name asc", "lastModifiedDateTime desc"). 기본값: "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_recent_files">
|
||||
**설명:** OneDrive에서 최근에 액세스한 파일을 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `top` (integer, 선택사항): 검색할 항목 수 (최대 200). 기본값: 25.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_shared_with_me">
|
||||
**설명:** 사용자와 공유된 파일과 폴더를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `top` (integer, 선택사항): 검색할 항목 수 (최대 200). 기본값: 50.
|
||||
- `orderby` (string, 선택사항): 필드별 정렬. 기본값: "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_file_by_path">
|
||||
**설명:** 경로로 특정 파일 또는 폴더에 대한 정보를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_path` (string, 필수): 파일 또는 폴더 경로 (예: 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/download_file_by_path">
|
||||
**설명:** 경로로 OneDrive에서 파일을 다운로드합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_path` (string, 필수): 파일 경로 (예: 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
@@ -183,6 +226,62 @@ crew = Crew(
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 파일 업로드 및 관리
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 파일 작업에 특화된 에이전트 생성
|
||||
file_operator = Agent(
|
||||
role="파일 운영자",
|
||||
goal="파일을 정확하게 업로드, 다운로드 및 관리",
|
||||
backstory="파일 처리 및 콘텐츠 관리에 능숙한 AI 어시스턴트.",
|
||||
apps=['microsoft_onedrive/upload_file', 'microsoft_onedrive/download_file', 'microsoft_onedrive/get_file_info']
|
||||
)
|
||||
|
||||
# 파일 업로드 및 관리 작업
|
||||
file_management_task = Task(
|
||||
description="'report.txt'라는 이름의 텍스트 파일을 'This is a sample report for the project.' 내용으로 업로드한 다음 업로드된 파일에 대한 정보를 가져오세요.",
|
||||
agent=file_operator,
|
||||
expected_output="파일이 성공적으로 업로드되고 파일 정보가 검색됨."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[file_operator],
|
||||
tasks=[file_management_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 파일 정리 및 공유
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 파일 정리 및 공유를 위한 에이전트 생성
|
||||
file_organizer = Agent(
|
||||
role="파일 정리자",
|
||||
goal="파일을 정리하고 협업을 위한 공유 링크 생성",
|
||||
backstory="파일 정리 및 공유 권한 관리에 뛰어난 AI 어시스턴트.",
|
||||
apps=['microsoft_onedrive/search_files', 'microsoft_onedrive/move_item', 'microsoft_onedrive/share_item', 'microsoft_onedrive/create_folder']
|
||||
)
|
||||
|
||||
# 파일 정리 및 공유 작업
|
||||
organize_share_task = Task(
|
||||
description="이름에 'presentation'이 포함된 파일을 검색하고, '프레젠테이션'이라는 폴더를 만든 다음, 찾은 파일을 이 폴더로 이동하고 폴더에 대한 읽기 전용 공유 링크를 생성하세요.",
|
||||
agent=file_organizer,
|
||||
expected_output="파일이 '프레젠테이션' 폴더로 정리되고 공유 링크가 생성됨."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[file_organizer],
|
||||
tasks=[organize_share_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 일반적인 문제
|
||||
@@ -196,6 +295,30 @@ crew.kickoff()
|
||||
|
||||
- 파일 업로드 시 `file_name`과 `content`가 제공되는지 확인하세요.
|
||||
- 바이너리 파일의 경우 내용이 Base64로 인코딩되어야 합니다.
|
||||
- OneDrive에 대한 쓰기 권한이 있는지 확인하세요.
|
||||
|
||||
**파일/폴더 ID 문제**
|
||||
|
||||
- 특정 파일 또는 폴더에 액세스할 때 항목 ID가 올바른지 다시 확인하세요.
|
||||
- 항목 ID는 `list_files` 또는 `search_files`와 같은 다른 작업에서 반환됩니다.
|
||||
- 참조하는 항목이 존재하고 액세스 가능한지 확인하세요.
|
||||
|
||||
**검색 및 필터 작업**
|
||||
|
||||
- `search_files` 작업에 적절한 검색어를 사용하세요.
|
||||
- `filter` 매개변수의 경우 올바른 OData 문법을 사용하세요.
|
||||
|
||||
**파일 작업 (복사/이동)**
|
||||
|
||||
- `move_item`의 경우 `item_id`와 `parent_id`가 모두 제공되는지 확인하세요.
|
||||
- `copy_item`의 경우 `item_id`만 필요합니다. `parent_id`는 지정하지 않으면 루트로 기본 설정됩니다.
|
||||
- 대상 폴더가 존재하고 액세스 가능한지 확인하세요.
|
||||
|
||||
**공유 링크 생성**
|
||||
|
||||
- 공유 링크를 만들기 전에 항목이 존재하는지 확인하세요.
|
||||
- 공유 요구 사항에 따라 적절한 `type`과 `scope`를 선택하세요.
|
||||
- `anonymous` 범위는 로그인 없이 액세스를 허용합니다. `organization`은 조직 계정이 필요합니다.
|
||||
|
||||
### 도움 받기
|
||||
|
||||
|
||||
@@ -132,6 +132,74 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `companyName` (string, 선택사항): 연락처의 회사 이름.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/get_message">
|
||||
**설명:** ID로 특정 이메일 메시지를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `message_id` (string, 필수): 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록. 예: "id,subject,body,from,receivedDateTime". 기본값: "id,subject,body,from,toRecipients,receivedDateTime".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/reply_to_email">
|
||||
**설명:** 이메일 메시지에 회신합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `message_id` (string, 필수): 회신할 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `comment` (string, 필수): 회신 메시지 내용. 일반 텍스트 또는 HTML 가능. 원본 메시지가 이 내용 아래에 인용됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/forward_email">
|
||||
**설명:** 이메일 메시지를 전달합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `message_id` (string, 필수): 전달할 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `to_recipients` (array, 필수): 전달할 받는 사람의 이메일 주소 배열. 예: ["john@example.com", "jane@example.com"].
|
||||
- `comment` (string, 선택사항): 전달된 콘텐츠 위에 포함할 선택적 메시지. 일반 텍스트 또는 HTML 가능.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/mark_message_read">
|
||||
**설명:** 메시지를 읽음 또는 읽지 않음으로 표시합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `message_id` (string, 필수): 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `is_read` (boolean, 필수): 읽음으로 표시하려면 true, 읽지 않음으로 표시하려면 false로 설정합니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_message">
|
||||
**설명:** 이메일 메시지를 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `message_id` (string, 필수): 삭제할 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/update_event">
|
||||
**설명:** 기존 캘린더 이벤트를 업데이트합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `event_id` (string, 필수): 이벤트의 고유 식별자. get_calendar_events 작업에서 얻을 수 있습니다.
|
||||
- `subject` (string, 선택사항): 이벤트의 새 제목/제목.
|
||||
- `start_time` (string, 선택사항): ISO 8601 형식의 새 시작 시간 (예: "2024-01-20T10:00:00"). 필수: 이 필드 사용 시 start_timezone도 제공해야 합니다.
|
||||
- `start_timezone` (string, 선택사항): 시작 시간의 시간대. start_time 업데이트 시 필수. 예: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `end_time` (string, 선택사항): ISO 8601 형식의 새 종료 시간. 필수: 이 필드 사용 시 end_timezone도 제공해야 합니다.
|
||||
- `end_timezone` (string, 선택사항): 종료 시간의 시간대. end_time 업데이트 시 필수. 예: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `location` (string, 선택사항): 이벤트의 새 위치.
|
||||
- `body` (string, 선택사항): 이벤트의 새 본문/설명. HTML 형식 지원.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_event">
|
||||
**설명:** 캘린더 이벤트를 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `event_id` (string, 필수): 삭제할 이벤트의 고유 식별자. get_calendar_events 작업에서 얻을 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
@@ -165,6 +233,62 @@ crew = Crew(
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 이메일 관리 및 검색
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 이메일 관리에 특화된 에이전트 생성
|
||||
email_manager = Agent(
|
||||
role="이메일 관리자",
|
||||
goal="이메일 메시지를 검색하고 가져와 정리",
|
||||
backstory="이메일 정리 및 관리에 능숙한 AI 어시스턴트.",
|
||||
apps=['microsoft_outlook/get_messages']
|
||||
)
|
||||
|
||||
# 이메일 검색 및 가져오기 작업
|
||||
search_emails_task = Task(
|
||||
description="최신 읽지 않은 이메일 20건을 가져와 가장 중요한 것들의 요약을 제공하세요.",
|
||||
agent=email_manager,
|
||||
expected_output="주요 읽지 않은 이메일의 요약과 핵심 세부 정보."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[email_manager],
|
||||
tasks=[search_emails_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 캘린더 및 연락처 관리
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 캘린더 및 연락처 관리를 위한 에이전트 생성
|
||||
scheduler = Agent(
|
||||
role="캘린더 및 연락처 관리자",
|
||||
goal="캘린더 이벤트를 관리하고 연락처 정보를 유지",
|
||||
backstory="일정 관리 및 연락처 정리를 담당하는 AI 어시스턴트.",
|
||||
apps=['microsoft_outlook/create_calendar_event', 'microsoft_outlook/get_calendar_events', 'microsoft_outlook/create_contact']
|
||||
)
|
||||
|
||||
# 회의 생성 및 연락처 추가 작업
|
||||
schedule_task = Task(
|
||||
description="내일 오후 2시 '팀 회의' 제목으로 '회의실 A' 장소의 캘린더 이벤트를 만들고, 'john.smith@example.com' 이메일과 '프로젝트 매니저' 직책으로 'John Smith'의 새 연락처를 추가하세요.",
|
||||
agent=scheduler,
|
||||
expected_output="캘린더 이벤트가 생성되고 새 연락처가 추가됨."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[scheduler],
|
||||
tasks=[schedule_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 일반적인 문제
|
||||
@@ -173,11 +297,29 @@ crew.kickoff()
|
||||
|
||||
- Microsoft 계정이 이메일, 캘린더 및 연락처 액세스에 필요한 권한을 가지고 있는지 확인하세요.
|
||||
- 필요한 범위: `Mail.Read`, `Mail.Send`, `Calendars.Read`, `Calendars.ReadWrite`, `Contacts.Read`, `Contacts.ReadWrite`.
|
||||
- OAuth 연결에 필요한 모든 범위가 포함되어 있는지 확인하세요.
|
||||
|
||||
**이메일 보내기 문제**
|
||||
|
||||
- `send_email`에 `to_recipients`, `subject`, `body`가 제공되는지 확인하세요.
|
||||
- 이메일 주소가 올바르게 형식화되어 있는지 확인하세요.
|
||||
- 계정에 `Mail.Send` 권한이 있는지 확인하세요.
|
||||
|
||||
**캘린더 이벤트 생성**
|
||||
|
||||
- `subject`, `start_datetime`, `end_datetime`이 제공되는지 확인하세요.
|
||||
- 날짜/시간 필드에 적절한 ISO 8601 형식을 사용하세요 (예: '2024-01-20T10:00:00').
|
||||
- 이벤트가 잘못된 시간에 표시되는 경우 시간대 설정을 확인하세요.
|
||||
|
||||
**연락처 관리**
|
||||
|
||||
- `create_contact`의 경우 필수인 `displayName`이 제공되는지 확인하세요.
|
||||
- `emailAddresses`를 제공할 때 `address`와 `name` 속성이 있는 올바른 객체 형식을 사용하세요.
|
||||
|
||||
**검색 및 필터 문제**
|
||||
|
||||
- `filter` 매개변수에 올바른 OData 문법을 사용하세요.
|
||||
- 날짜 필터의 경우 ISO 8601 형식을 사용하세요 (예: "receivedDateTime ge '2024-01-01T00:00:00Z'").
|
||||
|
||||
### 도움 받기
|
||||
|
||||
|
||||
@@ -77,6 +77,17 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drives">
|
||||
**설명:** SharePoint 사이트의 모든 문서 라이브러리(드라이브)를 나열합니다. 파일 작업을 사용하기 전에 사용 가능한 라이브러리를 찾으려면 이 작업을 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `top` (integer, 선택사항): 페이지당 반환할 최대 드라이브 수 (1-999). 기본값: 100
|
||||
- `skip_token` (string, 선택사항): 다음 결과 페이지를 가져오기 위한 이전 응답의 페이지네이션 토큰.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'id,name,webUrl,driveType').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_site_lists">
|
||||
**설명:** SharePoint 사이트의 모든 목록을 가져옵니다.
|
||||
|
||||
@@ -145,20 +156,317 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drive_items">
|
||||
**설명:** SharePoint 문서 라이브러리에서 파일과 폴더를 가져옵니다.
|
||||
<Accordion title="microsoft_sharepoint/list_files">
|
||||
**설명:** SharePoint 문서 라이브러리에서 파일과 폴더를 가져옵니다. 기본적으로 루트 폴더를 나열하지만 folder_id를 제공하여 하위 폴더로 이동할 수 있습니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): SharePoint 사이트의 ID.
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `folder_id` (string, 선택사항): 내용을 나열할 폴더의 ID. 루트 폴더의 경우 'root'를 사용하거나 이전 list_files 호출에서 가져온 폴더 ID를 제공하세요. 기본값: 'root'
|
||||
- `top` (integer, 선택사항): 페이지당 반환할 최대 항목 수 (1-1000). 기본값: 50
|
||||
- `skip_token` (string, 선택사항): 다음 결과 페이지를 가져오기 위한 이전 응답의 페이지네이션 토큰.
|
||||
- `orderby` (string, 선택사항): 결과 정렬 순서 (예: 'name asc', 'size desc', 'lastModifiedDateTime desc'). 기본값: 'name asc'
|
||||
- `filter` (string, 선택사항): 결과를 좁히기 위한 OData 필터 (예: 'file ne null'은 파일만, 'folder ne null'은 폴더만).
|
||||
- `select` (string, 선택사항): 반환할 필드의 쉼표로 구분된 목록 (예: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_drive_item">
|
||||
**설명:** SharePoint 문서 라이브러리에서 파일 또는 폴더를 삭제합니다.
|
||||
<Accordion title="microsoft_sharepoint/delete_file">
|
||||
**설명:** SharePoint 문서 라이브러리에서 파일 또는 폴더를 삭제합니다. 폴더의 경우 모든 내용이 재귀적으로 삭제됩니다. 항목은 사이트 휴지통으로 이동됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): SharePoint 사이트의 ID.
|
||||
- `item_id` (string, 필수): 삭제할 파일 또는 폴더의 ID.
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): 삭제할 파일 또는 폴더의 고유 식별자. list_files에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_files_by_path">
|
||||
**설명:** 경로로 SharePoint 문서 라이브러리 폴더의 파일과 폴더를 나열합니다. 깊은 탐색을 위해 여러 list_files 호출보다 더 효율적입니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `folder_path` (string, 필수): 앞뒤 슬래시 없이 폴더의 전체 경로 (예: 'Documents', 'Reports/2024/Q1').
|
||||
- `top` (integer, 선택사항): 페이지당 반환할 최대 항목 수 (1-1000). 기본값: 50
|
||||
- `skip_token` (string, 선택사항): 다음 결과 페이지를 가져오기 위한 이전 응답의 페이지네이션 토큰.
|
||||
- `orderby` (string, 선택사항): 결과 정렬 순서 (예: 'name asc', 'size desc'). 기본값: 'name asc'
|
||||
- `select` (string, 선택사항): 반환할 필드의 쉼표로 구분된 목록 (예: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/download_file">
|
||||
**설명:** SharePoint 문서 라이브러리에서 원시 파일 내용을 다운로드합니다. 일반 텍스트 파일(.txt, .csv, .json)에만 사용하세요. Excel 파일의 경우 Excel 전용 작업을 사용하세요. Word 파일의 경우 get_word_document_content를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): 다운로드할 파일의 고유 식별자. list_files 또는 list_files_by_path에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_file_info">
|
||||
**설명:** SharePoint 문서 라이브러리의 특정 파일 또는 폴더에 대한 자세한 메타데이터를 가져옵니다. 이름, 크기, 생성/수정 날짜 및 작성자 정보가 포함됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): 파일 또는 폴더의 고유 식별자. list_files 또는 list_files_by_path에서 가져오세요.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'id,name,size,createdDateTime,lastModifiedDateTime,webUrl,createdBy,lastModifiedBy').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_folder">
|
||||
**설명:** SharePoint 문서 라이브러리에 새 폴더를 만듭니다. 기본적으로 루트에 폴더를 만들며 하위 폴더를 만들려면 parent_id를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `folder_name` (string, 필수): 새 폴더의 이름. 사용할 수 없는 문자: \ / : * ? " < > |
|
||||
- `parent_id` (string, 선택사항): 상위 폴더의 ID. 문서 라이브러리 루트의 경우 'root'를 사용하거나 list_files에서 가져온 폴더 ID를 제공하세요. 기본값: 'root'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/search_files">
|
||||
**설명:** 키워드로 SharePoint 문서 라이브러리에서 파일과 폴더를 검색합니다. 파일 이름, 폴더 이름 및 Office 문서의 파일 내용을 검색합니다. 와일드카드나 특수 문자를 사용하지 마세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `query` (string, 필수): 검색 키워드 (예: 'report', 'budget 2024'). *.txt와 같은 와일드카드는 지원되지 않습니다.
|
||||
- `top` (integer, 선택사항): 페이지당 반환할 최대 결과 수 (1-1000). 기본값: 50
|
||||
- `skip_token` (string, 선택사항): 다음 결과 페이지를 가져오기 위한 이전 응답의 페이지네이션 토큰.
|
||||
- `select` (string, 선택사항): 반환할 필드의 쉼표로 구분된 목록 (예: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/copy_file">
|
||||
**설명:** SharePoint 내에서 파일 또는 폴더를 새 위치로 복사합니다. 원본 항목은 변경되지 않습니다. 대용량 파일의 경우 복사 작업은 비동기적입니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): 복사할 파일 또는 폴더의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `destination_folder_id` (string, 필수): 대상 폴더의 ID. 루트 폴더의 경우 'root'를 사용하거나 list_files에서 가져온 폴더 ID를 사용하세요.
|
||||
- `new_name` (string, 선택사항): 복사본의 새 이름. 제공하지 않으면 원래 이름이 사용됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/move_file">
|
||||
**설명:** SharePoint 내에서 파일 또는 폴더를 새 위치로 이동합니다. 항목은 원래 위치에서 제거됩니다. 폴더의 경우 모든 내용도 함께 이동됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): 이동할 파일 또는 폴더의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `destination_folder_id` (string, 필수): 대상 폴더의 ID. 루트 폴더의 경우 'root'를 사용하거나 list_files에서 가져온 폴더 ID를 사용하세요.
|
||||
- `new_name` (string, 선택사항): 이동된 항목의 새 이름. 제공하지 않으면 원래 이름이 유지됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_worksheets">
|
||||
**설명:** SharePoint 문서 라이브러리에 저장된 Excel 통합 문서의 모든 워크시트(탭)를 나열합니다. 반환된 워크시트 이름을 다른 Excel 작업에 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'id,name,position,visibility').
|
||||
- `filter` (string, 선택사항): OData 필터 표현식 (예: "visibility eq 'Visible'"로 숨겨진 시트 제외).
|
||||
- `top` (integer, 선택사항): 반환할 최대 워크시트 수. 최소: 1, 최대: 999
|
||||
- `orderby` (string, 선택사항): 정렬 순서 (예: 'position asc'로 탭 순서대로 반환).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_worksheet">
|
||||
**설명:** SharePoint 문서 라이브러리에 저장된 Excel 통합 문서에 새 워크시트(탭)를 만듭니다. 새 시트는 탭 목록의 끝에 추가됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `name` (string, 필수): 새 워크시트의 이름. 최대 31자. 사용할 수 없는 문자: \ / * ? : [ ]. 통합 문서 내에서 고유해야 합니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_range_data">
|
||||
**설명:** SharePoint에 저장된 Excel 워크시트의 특정 범위에서 셀 값을 가져옵니다. 크기를 모르는 상태에서 모든 데이터를 읽으려면 대신 get_excel_used_range를 사용하세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 읽을 워크시트(탭)의 이름. get_excel_worksheets에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `range` (string, 필수): A1 표기법의 셀 범위 (예: 'A1:C10', 'A:C', '1:5', 'A1').
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/update_excel_range_data">
|
||||
**설명:** SharePoint에 저장된 Excel 워크시트의 특정 범위에 값을 씁니다. 기존 셀 내용을 덮어씁니다. values 배열의 크기는 범위 크기와 정확히 일치해야 합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 업데이트할 워크시트(탭)의 이름. get_excel_worksheets에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `range` (string, 필수): 값을 쓸 A1 표기법의 셀 범위 (예: 'A1:C3'은 3x3 블록).
|
||||
- `values` (array, 필수): 2D 값 배열 (셀을 포함하는 행). A1:B2의 예: [["Header1", "Header2"], ["Value1", "Value2"]]. 셀을 지우려면 null을 사용하세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range_metadata">
|
||||
**설명:** 실제 셀 값 없이 워크시트에서 사용된 범위의 메타데이터(주소 및 크기)만 반환합니다. 대용량 파일에서 데이터를 청크로 읽기 전에 스프레드시트 크기를 파악하는 데 이상적입니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 읽을 워크시트(탭)의 이름. get_excel_worksheets에서 가져오세요. 대소문자를 구분합니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range">
|
||||
**설명:** SharePoint에 저장된 워크시트에서 데이터가 포함된 모든 셀을 가져옵니다. 2MB보다 큰 파일에는 사용하지 마세요. 대용량 파일의 경우 먼저 get_excel_used_range_metadata를 사용한 다음 get_excel_range_data로 작은 청크로 읽으세요.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 읽을 워크시트(탭)의 이름. get_excel_worksheets에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'address,values,formulas,numberFormat,text,rowCount,columnCount').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_cell">
|
||||
**설명:** SharePoint의 Excel 파일에서 행과 열 인덱스로 단일 셀의 값을 가져옵니다. 인덱스는 0 기반입니다 (행 0 = Excel 행 1, 열 0 = 열 A).
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 워크시트(탭)의 이름. get_excel_worksheets에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `row` (integer, 필수): 0 기반 행 인덱스 (행 0 = Excel 행 1). 유효 범위: 0-1048575
|
||||
- `column` (integer, 필수): 0 기반 열 인덱스 (열 0 = A, 열 1 = B). 유효 범위: 0-16383
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table">
|
||||
**설명:** 셀 범위를 필터링, 정렬 및 구조화된 데이터 기능이 있는 서식이 지정된 Excel 테이블로 변환합니다. 테이블을 만들면 add_excel_table_row로 데이터를 추가할 수 있습니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 데이터 범위가 포함된 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
- `range` (string, 필수): 헤더와 데이터를 포함하여 테이블로 변환할 셀 범위 (예: 'A1:D10'에서 A1:D1은 열 헤더).
|
||||
- `has_headers` (boolean, 선택사항): 첫 번째 행에 열 헤더가 포함되어 있으면 true로 설정. 기본값: true
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_tables">
|
||||
**설명:** SharePoint에 저장된 특정 Excel 워크시트의 모든 테이블을 나열합니다. id, name, showHeaders 및 showTotals를 포함한 테이블 속성을 반환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 테이블을 가져올 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table_row">
|
||||
**설명:** SharePoint 파일의 Excel 테이블 끝에 새 행을 추가합니다. values 배열은 테이블의 열 수와 같은 수의 요소를 가져야 합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 테이블이 포함된 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
- `table_name` (string, 필수): 행을 추가할 테이블의 이름 (예: 'Table1'). get_excel_tables에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `values` (array, 필수): 새 행의 셀 값 배열로 테이블 순서대로 열당 하나씩 (예: ["John Doe", "john@example.com", 25]).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_table_data">
|
||||
**설명:** SharePoint 파일의 Excel 테이블에서 모든 행을 데이터 범위로 가져옵니다. 정확한 범위를 알 필요가 없으므로 구조화된 테이블 작업 시 get_excel_range_data보다 쉽습니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 테이블이 포함된 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
- `table_name` (string, 필수): 데이터를 가져올 테이블의 이름 (예: 'Table1'). get_excel_tables에서 가져오세요. 대소문자를 구분합니다.
|
||||
- `select` (string, 선택사항): 반환할 속성의 쉼표로 구분된 목록 (예: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_chart">
|
||||
**설명:** SharePoint에 저장된 Excel 워크시트에 데이터 범위에서 차트 시각화를 만듭니다. 차트는 워크시트에 포함됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 차트를 만들 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
- `chart_type` (string, 필수): 차트 유형 (예: 'ColumnClustered', 'ColumnStacked', 'Line', 'LineMarkers', 'Pie', 'Bar', 'BarClustered', 'Area', 'Scatter', 'Doughnut').
|
||||
- `source_data` (string, 필수): 헤더를 포함한 A1 표기법의 차트 데이터 범위 (예: 'A1:B10').
|
||||
- `series_by` (string, 선택사항): 데이터 계열 구성 방법: 'Auto', 'Columns' 또는 'Rows'. 기본값: 'Auto'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_charts">
|
||||
**설명:** SharePoint에 저장된 Excel 워크시트에 포함된 모든 차트를 나열합니다. id, name, chartType, height, width 및 position을 포함한 차트 속성을 반환합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 차트를 나열할 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_worksheet">
|
||||
**설명:** SharePoint에 저장된 Excel 통합 문서에서 워크시트(탭)와 모든 내용을 영구적으로 제거합니다. 실행 취소할 수 없습니다. 통합 문서에는 최소 하나의 워크시트가 있어야 합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 삭제할 워크시트의 이름. 대소문자를 구분합니다. 이 시트의 모든 데이터, 테이블 및 차트가 영구적으로 제거됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_table">
|
||||
**설명:** SharePoint의 Excel 워크시트에서 테이블을 제거합니다. 테이블 구조(필터링, 서식, 테이블 기능)는 삭제되지만 기본 셀 데이터는 보존됩니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
- `worksheet_name` (string, 필수): 테이블이 포함된 워크시트의 이름. get_excel_worksheets에서 가져오세요.
|
||||
- `table_name` (string, 필수): 삭제할 테이블의 이름 (예: 'Table1'). get_excel_tables에서 가져오세요. 테이블 삭제 후에도 셀의 데이터는 유지됩니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_names">
|
||||
**설명:** SharePoint에 저장된 Excel 통합 문서에 정의된 모든 명명된 범위를 가져옵니다. 명명된 범위는 셀 범위에 대한 사용자 정의 레이블입니다 (예: 'SalesData'는 A1:D100을 가리킴).
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Excel 파일의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_word_document_content">
|
||||
**설명:** SharePoint 문서 라이브러리에 저장된 Word 문서(.docx)에서 텍스트 내용을 다운로드하고 추출합니다. SharePoint에서 Word 문서를 읽는 권장 방법입니다.
|
||||
|
||||
**매개변수:**
|
||||
- `site_id` (string, 필수): get_sites에서 가져온 전체 SharePoint 사이트 식별자.
|
||||
- `drive_id` (string, 필수): 문서 라이브러리의 ID. 먼저 get_drives를 호출하여 유효한 드라이브 ID를 가져오세요.
|
||||
- `item_id` (string, 필수): SharePoint에 있는 Word 문서(.docx)의 고유 식별자. list_files 또는 search_files에서 가져오세요.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -107,6 +107,86 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `join_web_url` (string, 필수): 검색할 회의의 웹 참가 URL.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/search_online_meetings_by_meeting_id">
|
||||
**설명:** 외부 Meeting ID로 온라인 회의를 검색합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `join_meeting_id` (string, 필수): 참석자가 참가할 때 사용하는 회의 ID(숫자 코드). 회의 초대에 표시되는 joinMeetingId이며, Graph API meeting id가 아닙니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_meeting">
|
||||
**설명:** 특정 온라인 회의의 세부 정보를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `meeting_id` (string, 필수): Graph API 회의 ID(긴 영숫자 문자열). create_meeting 또는 search_online_meetings 작업에서 얻을 수 있습니다. 숫자 joinMeetingId와 다릅니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_team_members">
|
||||
**설명:** 특정 팀의 멤버를 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `team_id` (string, 필수): 팀의 고유 식별자. get_teams 작업에서 얻을 수 있습니다.
|
||||
- `top` (integer, 선택사항): 페이지당 검색할 멤버 수 (1-999). 기본값: 100.
|
||||
- `skip_token` (string, 선택사항): 이전 응답의 페이지네이션 토큰. 응답에 @odata.nextLink가 포함된 경우 $skiptoken 매개변수 값을 추출하여 여기에 전달하면 다음 페이지 결과를 가져올 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/create_channel">
|
||||
**설명:** 팀에 새 채널을 만듭니다.
|
||||
|
||||
**매개변수:**
|
||||
- `team_id` (string, 필수): 팀의 고유 식별자. get_teams 작업에서 얻을 수 있습니다.
|
||||
- `display_name` (string, 필수): Teams에 표시되는 채널 이름. 팀 내에서 고유해야 합니다. 최대 50자.
|
||||
- `description` (string, 선택사항): 채널 목적을 설명하는 선택적 설명. 채널 세부 정보에 표시됩니다. 최대 1024자.
|
||||
- `membership_type` (string, 선택사항): 채널 가시성. 옵션: standard, private. "standard" = 모든 팀 멤버에게 표시, "private" = 명시적으로 추가된 멤버에게만 표시. 기본값: standard.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_message_replies">
|
||||
**설명:** 채널의 특정 메시지에 대한 회신을 가져옵니다.
|
||||
|
||||
**매개변수:**
|
||||
- `team_id` (string, 필수): 팀의 고유 식별자. get_teams 작업에서 얻을 수 있습니다.
|
||||
- `channel_id` (string, 필수): 채널의 고유 식별자. get_channels 작업에서 얻을 수 있습니다.
|
||||
- `message_id` (string, 필수): 상위 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `top` (integer, 선택사항): 페이지당 검색할 회신 수 (1-50). 기본값: 50.
|
||||
- `skip_token` (string, 선택사항): 이전 응답의 페이지네이션 토큰. 응답에 @odata.nextLink가 포함된 경우 $skiptoken 매개변수 값을 추출하여 여기에 전달하면 다음 페이지 결과를 가져올 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/reply_to_message">
|
||||
**설명:** Teams 채널의 메시지에 회신합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `team_id` (string, 필수): 팀의 고유 식별자. get_teams 작업에서 얻을 수 있습니다.
|
||||
- `channel_id` (string, 필수): 채널의 고유 식별자. get_channels 작업에서 얻을 수 있습니다.
|
||||
- `message_id` (string, 필수): 회신할 메시지의 고유 식별자. get_messages 작업에서 얻을 수 있습니다.
|
||||
- `message` (string, 필수): 회신 내용. HTML의 경우 서식 태그 포함. 텍스트의 경우 일반 텍스트만.
|
||||
- `content_type` (string, 선택사항): 콘텐츠 형식. 옵션: html, text. "text"는 일반 텍스트, "html"은 서식이 있는 리치 텍스트. 기본값: text.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/update_meeting">
|
||||
**설명:** 기존 온라인 회의를 업데이트합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `meeting_id` (string, 필수): 회의의 고유 식별자. create_meeting 또는 search_online_meetings 작업에서 얻을 수 있습니다.
|
||||
- `subject` (string, 선택사항): 새 회의 제목.
|
||||
- `startDateTime` (string, 선택사항): 시간대가 포함된 ISO 8601 형식의 새 시작 시간. 예: "2024-01-20T10:00:00-08:00".
|
||||
- `endDateTime` (string, 선택사항): 시간대가 포함된 ISO 8601 형식의 새 종료 시간.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/delete_meeting">
|
||||
**설명:** 온라인 회의를 삭제합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `meeting_id` (string, 필수): 삭제할 회의의 고유 식별자. create_meeting 또는 search_online_meetings 작업에서 얻을 수 있습니다.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
@@ -140,6 +220,62 @@ crew = Crew(
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 메시징 및 커뮤니케이션
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 메시징에 특화된 에이전트 생성
|
||||
messenger = Agent(
|
||||
role="Teams 메신저",
|
||||
goal="Teams 채널에서 메시지 전송 및 검색",
|
||||
backstory="팀 커뮤니케이션 및 메시지 관리에 능숙한 AI 어시스턴트.",
|
||||
apps=['microsoft_teams/send_message', 'microsoft_teams/get_messages']
|
||||
)
|
||||
|
||||
# 메시지 전송 및 최근 메시지 검색 작업
|
||||
messaging_task = Task(
|
||||
description="'your_team_id' 팀의 General 채널에 'Hello team! This is an automated update from our AI assistant.' 메시지를 보낸 다음 해당 채널의 최근 10개 메시지를 검색하세요.",
|
||||
agent=messenger,
|
||||
expected_output="메시지가 성공적으로 전송되고 최근 메시지가 검색됨."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[messenger],
|
||||
tasks=[messaging_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
### 회의 관리
|
||||
|
||||
```python
|
||||
from crewai import Agent, Task, Crew
|
||||
|
||||
# 회의 관리를 위한 에이전트 생성
|
||||
meeting_scheduler = Agent(
|
||||
role="회의 스케줄러",
|
||||
goal="Teams 회의 생성 및 관리",
|
||||
backstory="회의 일정 관리 및 정리를 담당하는 AI 어시스턴트.",
|
||||
apps=['microsoft_teams/create_meeting', 'microsoft_teams/search_online_meetings_by_join_url']
|
||||
)
|
||||
|
||||
# 회의 생성 작업
|
||||
schedule_meeting_task = Task(
|
||||
description="내일 오전 10시에 1시간 동안 진행되는 '주간 팀 동기화' 제목의 Teams 회의를 생성하세요 (시간대가 포함된 적절한 ISO 8601 형식 사용).",
|
||||
agent=meeting_scheduler,
|
||||
expected_output="회의 세부 정보와 함께 Teams 회의가 성공적으로 생성됨."
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[meeting_scheduler],
|
||||
tasks=[schedule_meeting_task]
|
||||
)
|
||||
|
||||
crew.kickoff()
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 일반적인 문제
|
||||
@@ -148,11 +284,35 @@ crew.kickoff()
|
||||
|
||||
- Microsoft 계정이 Teams 액세스에 필요한 권한을 가지고 있는지 확인하세요.
|
||||
- 필요한 범위: `Team.ReadBasic.All`, `Channel.ReadBasic.All`, `ChannelMessage.Send`, `ChannelMessage.Read.All`, `OnlineMeetings.ReadWrite`, `OnlineMeetings.Read`.
|
||||
- OAuth 연결에 필요한 모든 범위가 포함되어 있는지 확인하세요.
|
||||
|
||||
**팀 및 채널 액세스**
|
||||
|
||||
- 액세스하려는 팀의 멤버인지 확인하세요.
|
||||
- 팀 및 채널 ID가 올바른지 다시 확인하세요.
|
||||
- 팀 및 채널 ID는 `get_teams` 및 `get_channels` 작업을 사용하여 얻을 수 있습니다.
|
||||
|
||||
**메시지 전송 문제**
|
||||
|
||||
- `send_message`에 `team_id`, `channel_id`, `message`가 제공되는지 확인하세요.
|
||||
- 지정된 채널에 메시지를 보낼 권한이 있는지 확인하세요.
|
||||
- 메시지 형식에 따라 적절한 `content_type`(text 또는 html)을 선택하세요.
|
||||
|
||||
**회의 생성**
|
||||
|
||||
- `subject`, `startDateTime`, `endDateTime`이 제공되는지 확인하세요.
|
||||
- 날짜/시간 필드에 시간대가 포함된 적절한 ISO 8601 형식을 사용하세요 (예: '2024-01-20T10:00:00-08:00').
|
||||
- 회의 시간이 미래인지 확인하세요.
|
||||
|
||||
**메시지 검색 제한**
|
||||
|
||||
- `get_messages` 작업은 요청당 최대 50개 메시지만 검색할 수 있습니다.
|
||||
- 메시지는 역시간순(최신순)으로 반환됩니다.
|
||||
|
||||
**회의 검색**
|
||||
|
||||
- `search_online_meetings_by_join_url`의 경우 참가 URL이 정확하고 올바르게 형식화되어 있는지 확인하세요.
|
||||
- URL은 완전한 Teams 회의 참가 URL이어야 합니다.
|
||||
|
||||
### 도움 받기
|
||||
|
||||
|
||||
@@ -97,6 +97,26 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=your_enterprise_token
|
||||
- `file_id` (string, 필수): 삭제할 문서의 ID.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/copy_document">
|
||||
**설명:** OneDrive의 새 위치에 문서를 복사합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_id` (string, 필수): 복사할 문서의 ID.
|
||||
- `name` (string, 선택사항): 복사된 문서의 새 이름.
|
||||
- `parent_id` (string, 선택사항): 대상 폴더의 ID (기본값: 루트).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/move_document">
|
||||
**설명:** OneDrive의 새 위치로 문서를 이동합니다.
|
||||
|
||||
**매개변수:**
|
||||
- `file_id` (string, 필수): 이동할 문서의 ID.
|
||||
- `parent_id` (string, 필수): 대상 폴더의 ID.
|
||||
- `name` (string, 선택사항): 이동된 문서의 새 이름.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 사용 예제
|
||||
|
||||
@@ -79,7 +79,7 @@ CrewAI AOP는 오픈 소스 프레임워크의 강력함에 프로덕션 배포,
|
||||
<Card
|
||||
title="Crew 배포"
|
||||
icon="rocket"
|
||||
href="/ko/enterprise/guides/deploy-crew"
|
||||
href="/ko/enterprise/guides/deploy-to-amp"
|
||||
>
|
||||
Crew 배포
|
||||
</Card>
|
||||
@@ -96,4 +96,4 @@ CrewAI AOP는 오픈 소스 프레임워크의 강력함에 프로덕션 배포,
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
자세한 안내를 원하시면 [배포 가이드](/ko/enterprise/guides/deploy-crew)를 확인하거나 아래 버튼을 클릭해 시작하세요.
|
||||
자세한 안내를 원하시면 [배포 가이드](/ko/enterprise/guides/deploy-to-amp)를 확인하거나 아래 버튼을 클릭해 시작하세요.
|
||||
|
||||
@@ -112,3 +112,9 @@ HITL 워크플로우는 다음과 같은 경우에 특히 유용합니다:
|
||||
- 민감하거나 고위험 작업
|
||||
- 인간의 판단이 필요한 창의적 과제
|
||||
- 컴플라이언스 및 규제 검토
|
||||
|
||||
## Enterprise 기능
|
||||
|
||||
<Card title="Flow HITL 관리 플랫폼" icon="users-gear" href="/ko/enterprise/features/flow-hitl-management">
|
||||
CrewAI Enterprise는 플랫폼 내 검토, 응답자 할당, 권한, 에스컬레이션 정책, SLA 관리, 동적 라우팅 및 전체 분석을 갖춘 Flow용 포괄적인 HITL 관리 시스템을 제공합니다. [자세히 알아보기 →](/ko/enterprise/features/flow-hitl-management)
|
||||
</Card>
|
||||
|
||||
115
docs/ko/observability/galileo.mdx
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: Galileo 갈릴레오
|
||||
description: CrewAI 추적 및 평가를 위한 Galileo 통합
|
||||
icon: telescope
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
이 가이드는 **Galileo**를 **CrewAI**와 통합하는 방법을 보여줍니다.
|
||||
포괄적인 추적 및 평가 엔지니어링을 위한 것입니다.
|
||||
이 가이드가 끝나면 CrewAI 에이전트를 추적할 수 있게 됩니다.
|
||||
성과를 모니터링하고 행동을 평가합니다.
|
||||
Galileo의 강력한 관측 플랫폼.
|
||||
|
||||
> **갈릴레오(Galileo)란 무엇인가요?**[Galileo](https://galileo.ai/)는 AI 평가 및 관찰 가능성입니다.
|
||||
엔드투엔드 추적, 평가,
|
||||
AI 애플리케이션 모니터링. 이를 통해 팀은 실제 사실을 포착할 수 있습니다.
|
||||
견고한 가드레일을 만들고 체계적인 실험을 실행하세요.
|
||||
내장된 실험 추적 및 성능 분석으로 신뢰성 보장
|
||||
AI 수명주기 전반에 걸쳐 투명성과 지속적인 개선을 제공합니다.
|
||||
|
||||
## 시작하기
|
||||
|
||||
이 튜토리얼은 [CrewAI 빠른 시작](/ko/quickstart.mdx)을 따르며 추가하는 방법을 보여줍니다.
|
||||
갈릴레오의 [CrewAIEventListener](https://v2docs.galileo.ai/sdk-api/python/reference/handlers/crewai/handler),
|
||||
이벤트 핸들러.
|
||||
자세한 내용은 갈릴레오 문서를 참고하세요.
|
||||
[CrewAI 애플리케이션에 Galileo 추가](https://v2docs.galileo.ai/how-to-guides/third-party-integrations/add-galileo-to-crewai/add-galileo-to-crewai)
|
||||
방법 안내.
|
||||
|
||||
> **참고**이 튜토리얼에서는 [CrewAI 빠른 시작](/ko/quickstart.mdx)을 완료했다고 가정합니다.
|
||||
완전한 포괄적인 예제를 원한다면 Galileo
|
||||
[CrewAI SDK 예제 저장소](https://github.com/rungalileo/sdk-examples/tree/main/python/agent/crew-ai).
|
||||
|
||||
### 1단계: 종속성 설치
|
||||
|
||||
앱에 필요한 종속성을 설치합니다.
|
||||
원하는 방법으로 가상 환경을 생성하고,
|
||||
그런 다음 다음을 사용하여 해당 환경 내에 종속성을 설치하십시오.
|
||||
선호하는 도구:
|
||||
|
||||
```bash
|
||||
uv add galileo
|
||||
```
|
||||
|
||||
### 2단계: [CrewAI 빠른 시작](/ko/quickstart.mdx)에서 .env 파일에 추가
|
||||
|
||||
```bash
|
||||
# Your Galileo API key
|
||||
GALILEO_API_KEY="your-galileo-api-key"
|
||||
|
||||
# Your Galileo project name
|
||||
GALILEO_PROJECT="your-galileo-project-name"
|
||||
|
||||
# The name of the Log stream you want to use for logging
|
||||
GALILEO_LOG_STREAM="your-galileo-log-stream "
|
||||
```
|
||||
|
||||
### 3단계: Galileo 이벤트 리스너 추가
|
||||
|
||||
Galileo로 로깅을 활성화하려면 `CrewAIEventListener`의 인스턴스를 생성해야 합니다.
|
||||
다음을 통해 Galileo CrewAI 핸들러 패키지를 가져옵니다.
|
||||
main.py 파일 상단에 다음 코드를 추가하세요.
|
||||
|
||||
```python
|
||||
from galileo.handlers.crewai.handler import CrewAIEventListener
|
||||
```
|
||||
|
||||
실행 함수 시작 시 이벤트 리스너를 생성합니다.
|
||||
|
||||
```python
|
||||
def run():
|
||||
# Create the event listener
|
||||
CrewAIEventListener()
|
||||
# The rest of your existing code goes here
|
||||
```
|
||||
|
||||
리스너 인스턴스를 생성하면 자동으로
|
||||
CrewAI에 등록되었습니다.
|
||||
|
||||
### 4단계: Crew Agent 실행
|
||||
|
||||
CrewAI CLI를 사용하여 Crew Agent를 실행하세요.
|
||||
|
||||
```bash
|
||||
crewai run
|
||||
```
|
||||
|
||||
### 5단계: Galileo에서 추적 보기
|
||||
|
||||
승무원 에이전트가 완료되면 흔적이 플러시되어 Galileo에 나타납니다.
|
||||
|
||||

|
||||
|
||||
## 갈릴레오 통합 이해
|
||||
|
||||
Galileo는 이벤트 리스너를 등록하여 CrewAI와 통합됩니다.
|
||||
승무원 실행 이벤트(예: 에이전트 작업, 도구 호출, 모델 응답)를 캡처합니다.
|
||||
관찰 가능성과 평가를 위해 이를 갈릴레오에 전달합니다.
|
||||
|
||||
### 이벤트 리스너 이해
|
||||
|
||||
`CrewAIEventListener()` 인스턴스를 생성하는 것이 전부입니다.
|
||||
CrewAI 실행을 위해 Galileo를 활성화하는 데 필요합니다. 인스턴스화되면 리스너는 다음을 수행합니다.
|
||||
|
||||
-CrewAI에 자동으로 등록됩니다.
|
||||
-환경 변수에서 Galileo 구성을 읽습니다.
|
||||
-모든 실행 데이터를 Galileo 프로젝트 및 다음에서 지정한 로그 스트림에 기록합니다.
|
||||
`GALILEO_PROJECT` 및 `GALILEO_LOG_STREAM`
|
||||
|
||||
추가 구성이나 코드 변경이 필요하지 않습니다.
|
||||
이 실행의 모든 데이터는 Galileo 프로젝트에 기록되며
|
||||
환경 구성에 따라 지정된 로그 스트림
|
||||
(예: GALILEO_PROJECT 및 GALILEO_LOG_STREAM)
|
||||
@@ -4,6 +4,74 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="26 jan 2026">
|
||||
## v1.9.0
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.9.0)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Funcionalidades
|
||||
- Adicionar suporte a saídas estruturadas e response_format em vários provedores
|
||||
- Adicionar ID de resposta às respostas de streaming
|
||||
- Adicionar ordenação de eventos com hierarquias pai-filho
|
||||
- Adicionar suporte à autenticação SSO Keycloak
|
||||
- Adicionar capacidades de manipulação de arquivos multimodais
|
||||
- Adicionar suporte nativo à API de respostas OpenAI
|
||||
- Adicionar utilitários de execução de tarefas A2A
|
||||
- Adicionar configuração de servidor A2A e geração de cartão de agente
|
||||
- Aprimorar sistema de eventos e expandir opções de transporte
|
||||
- Melhorar mecanismos de chamada de ferramentas
|
||||
|
||||
### Correções de Bugs
|
||||
- Aprimorar armazenamento de arquivos com cache de memória de fallback quando aiocache não está disponível
|
||||
- Garantir que lista de documentos não esteja vazia
|
||||
- Tratar sequências de parada do Bedrock adequadamente
|
||||
- Adicionar suporte à chave de API do Google Vertex
|
||||
- Aprimorar detecção de palavras de parada do modelo Azure
|
||||
- Melhorar tratamento de erros para HumanFeedbackPending na execução de fluxo
|
||||
- Corrigir desvinculação de tarefa do span de execução
|
||||
|
||||
### Documentação
|
||||
- Adicionar documentação de manipulação nativa de arquivos
|
||||
- Adicionar documentação da API de respostas OpenAI
|
||||
- Adicionar orientação de implementação de cartão de agente
|
||||
- Refinar documentação A2A
|
||||
- Atualizar changelog para v1.8.0
|
||||
|
||||
### Contribuidores
|
||||
@Anaisdg, @GininDenis, @Vidit-Ostwal, @greysonlalonde, @heitorado, @joaomdmoura, @koushiv777, @lorenzejay, @nicoferdi96, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="15 jan 2026">
|
||||
## v1.8.1
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.8.1)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Funcionalidades
|
||||
- Adicionar utilitários de execução de tarefas A2A
|
||||
- Adicionar configuração de servidor A2A e geração de cartão de agente
|
||||
- Adicionar mecanismos de transporte adicionais
|
||||
- Adicionar suporte à integração Galileo
|
||||
|
||||
### Correções de Bugs
|
||||
- Melhorar compatibilidade do modelo Azure
|
||||
- Expandir profundidade de inspeção de frame para detectar parent_flow
|
||||
- Resolver problemas de gerenciamento de span de execução de tarefas
|
||||
- Aprimorar tratamento de erros para cenários de feedback humano durante execução de fluxo
|
||||
|
||||
### Documentação
|
||||
- Adicionar documentação de cartão de agente A2A
|
||||
- Adicionar documentação de recurso de redação de PII
|
||||
|
||||
### Contribuidores
|
||||
@Anaisdg, @GininDenis, @greysonlalonde, @joaomdmoura, @koushiv777, @lorenzejay, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="08 jan 2026">
|
||||
## v1.8.0
|
||||
|
||||
|
||||
267
docs/pt-BR/concepts/files.mdx
Normal file
@@ -0,0 +1,267 @@
|
||||
---
|
||||
title: Arquivos
|
||||
description: Passe imagens, PDFs, áudio, vídeo e arquivos de texto para seus agentes para processamento multimodal.
|
||||
icon: file-image
|
||||
---
|
||||
|
||||
## Visão Geral
|
||||
|
||||
O CrewAI suporta entradas de arquivos multimodais nativos, permitindo que você passe imagens, PDFs, áudio, vídeo e arquivos de texto diretamente para seus agentes. Os arquivos são formatados automaticamente para os requisitos da API de cada provedor LLM.
|
||||
|
||||
<Note type="info" title="Dependência Opcional">
|
||||
O suporte a arquivos requer o pacote opcional `crewai-files`. Instale com:
|
||||
|
||||
```bash
|
||||
uv add 'crewai[file-processing]'
|
||||
```
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="Acesso Antecipado">
|
||||
A API de processamento de arquivos está atualmente em acesso antecipado.
|
||||
</Note>
|
||||
|
||||
## Tipos de Arquivo
|
||||
|
||||
O CrewAI suporta cinco tipos de arquivo específicos mais uma classe genérica `File` que detecta automaticamente o tipo:
|
||||
|
||||
| Tipo | Classe | Casos de Uso |
|
||||
|:-----|:------|:----------|
|
||||
| **Imagem** | `ImageFile` | Fotos, capturas de tela, diagramas, gráficos |
|
||||
| **PDF** | `PDFFile` | Documentos, relatórios, artigos |
|
||||
| **Áudio** | `AudioFile` | Gravações de voz, podcasts, reuniões |
|
||||
| **Vídeo** | `VideoFile` | Gravações de tela, apresentações |
|
||||
| **Texto** | `TextFile` | Arquivos de código, logs, arquivos de dados |
|
||||
| **Genérico** | `File` | Detecta automaticamente o tipo do conteúdo |
|
||||
|
||||
```python
|
||||
from crewai_files import File, ImageFile, PDFFile, AudioFile, VideoFile, TextFile
|
||||
|
||||
image = ImageFile(source="screenshot.png")
|
||||
pdf = PDFFile(source="report.pdf")
|
||||
audio = AudioFile(source="meeting.mp3")
|
||||
video = VideoFile(source="demo.mp4")
|
||||
text = TextFile(source="data.csv")
|
||||
|
||||
file = File(source="document.pdf")
|
||||
```
|
||||
|
||||
## Fontes de Arquivo
|
||||
|
||||
O parâmetro `source` aceita múltiplos tipos de entrada e detecta automaticamente o handler apropriado:
|
||||
|
||||
### De Caminho
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="./images/chart.png")
|
||||
```
|
||||
|
||||
### De URL
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile
|
||||
|
||||
image = ImageFile(source="https://example.com/image.png")
|
||||
```
|
||||
|
||||
### De Bytes
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, FileBytes
|
||||
|
||||
image_bytes = download_image_from_api()
|
||||
image = ImageFile(source=FileBytes(data=image_bytes, filename="downloaded.png"))
|
||||
image = ImageFile(source=image_bytes)
|
||||
```
|
||||
|
||||
## Usando Arquivos
|
||||
|
||||
Arquivos podem ser passados em múltiplos níveis, com níveis mais específicos tendo precedência.
|
||||
|
||||
### Com Crews
|
||||
|
||||
Passe arquivos ao iniciar uma crew:
|
||||
|
||||
```python
|
||||
from crewai import Crew
|
||||
from crewai_files import ImageFile
|
||||
|
||||
crew = Crew(agents=[analyst], tasks=[analysis_task])
|
||||
|
||||
result = crew.kickoff(
|
||||
inputs={"topic": "Q4 Sales"},
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
"report": PDFFile(source="quarterly_report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Com Tasks
|
||||
|
||||
Anexe arquivos a tasks específicas:
|
||||
|
||||
```python
|
||||
from crewai import Task
|
||||
from crewai_files import ImageFile
|
||||
|
||||
task = Task(
|
||||
description="Analise o gráfico de vendas e identifique tendências em {chart}",
|
||||
expected_output="Um resumo das principais tendências",
|
||||
input_files={
|
||||
"chart": ImageFile(source="sales_chart.png"),
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Com Flows
|
||||
|
||||
Passe arquivos para flows, que automaticamente herdam para crews:
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai_files import ImageFile
|
||||
|
||||
class AnalysisFlow(Flow):
|
||||
@start()
|
||||
def analyze(self):
|
||||
return self.analysis_crew.kickoff()
|
||||
|
||||
flow = AnalysisFlow()
|
||||
result = flow.kickoff(
|
||||
input_files={"image": ImageFile(source="data.png")}
|
||||
)
|
||||
```
|
||||
|
||||
### Com Agentes Standalone
|
||||
|
||||
Passe arquivos diretamente no kickoff do agente:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai_files import ImageFile
|
||||
|
||||
agent = Agent(
|
||||
role="Image Analyst",
|
||||
goal="Analyze images",
|
||||
backstory="Expert at visual analysis",
|
||||
llm="gpt-4o",
|
||||
)
|
||||
|
||||
result = agent.kickoff(
|
||||
messages="What's in this image?",
|
||||
input_files={"photo": ImageFile(source="photo.jpg")},
|
||||
)
|
||||
```
|
||||
|
||||
## Precedência de Arquivos
|
||||
|
||||
Quando arquivos são passados em múltiplos níveis, níveis mais específicos sobrescrevem os mais amplos:
|
||||
|
||||
```
|
||||
Flow input_files < Crew input_files < Task input_files
|
||||
```
|
||||
|
||||
Por exemplo, se tanto Flow quanto Task definem um arquivo chamado `"chart"`, a versão da Task é usada.
|
||||
|
||||
## Suporte por Provedor
|
||||
|
||||
Diferentes provedores suportam diferentes tipos de arquivo. O CrewAI formata automaticamente os arquivos para a API de cada provedor.
|
||||
|
||||
| Provedor | Imagem | PDF | Áudio | Vídeo | Texto |
|
||||
|:---------|:-----:|:---:|:-----:|:-----:|:----:|
|
||||
| **OpenAI** (API completions) | ✓ | | | | |
|
||||
| **OpenAI** (API responses) | ✓ | ✓ | ✓ | | |
|
||||
| **Anthropic** (claude-3.x) | ✓ | ✓ | | | |
|
||||
| **Google Gemini** (gemini-1.5, 2.0, 2.5) | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||
| **AWS Bedrock** (claude-3) | ✓ | ✓ | | | |
|
||||
| **Azure OpenAI** (gpt-4o) | ✓ | | ✓ | | |
|
||||
|
||||
<Note type="info" title="Gemini para Máximo Suporte de Arquivos">
|
||||
Os modelos Google Gemini suportam todos os tipos de arquivo incluindo vídeo (até 1 hora, 2GB). Use Gemini quando precisar processar conteúdo de vídeo.
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="Tipos de Arquivo Não Suportados">
|
||||
Se você passar um tipo de arquivo que o provedor não suporta (ex: vídeo para OpenAI), você receberá um `UnsupportedFileTypeError`. Escolha seu provedor baseado nos tipos de arquivo que você precisa processar.
|
||||
</Note>
|
||||
|
||||
## Como os Arquivos São Enviados
|
||||
|
||||
O CrewAI escolhe automaticamente o método ideal para enviar arquivos para cada provedor:
|
||||
|
||||
| Método | Descrição | Usado Quando |
|
||||
|:-------|:------------|:----------|
|
||||
| **Base64 Inline** | Arquivo embutido diretamente na requisição | Arquivos pequenos (< 5MB tipicamente) |
|
||||
| **API de Upload de Arquivo** | Arquivo enviado separadamente, referenciado por ID | Arquivos grandes que excedem o limite |
|
||||
| **Referência por URL** | URL direta passada para o modelo | Fonte do arquivo já é uma URL |
|
||||
|
||||
### Métodos de Transmissão por Provedor
|
||||
|
||||
| Provedor | Base64 Inline | API de Upload | Referências URL |
|
||||
|:---------|:-------------:|:---------------:|:--------------:|
|
||||
| **OpenAI** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Anthropic** | ✓ | ✓ (> 5 MB) | ✓ |
|
||||
| **Google Gemini** | ✓ | ✓ (> 20 MB) | ✓ |
|
||||
| **AWS Bedrock** | ✓ | | ✓ (S3 URIs) |
|
||||
| **Azure OpenAI** | ✓ | | ✓ |
|
||||
|
||||
<Note type="info" title="Otimização Automática">
|
||||
Você não precisa gerenciar isso. O CrewAI usa automaticamente o método mais eficiente baseado no tamanho do arquivo e nas capacidades do provedor. Provedores sem APIs de upload de arquivo usam base64 inline para todos os arquivos.
|
||||
</Note>
|
||||
|
||||
## Modos de Tratamento de Arquivo
|
||||
|
||||
Controle como os arquivos são processados quando excedem os limites do provedor:
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
image = ImageFile(source="large.png", mode="strict")
|
||||
image = ImageFile(source="large.png", mode="auto")
|
||||
image = ImageFile(source="large.png", mode="warn")
|
||||
pdf = PDFFile(source="large.pdf", mode="chunk")
|
||||
```
|
||||
|
||||
## Restrições por Provedor
|
||||
|
||||
Cada provedor tem limites específicos para tamanhos e dimensões de arquivo:
|
||||
|
||||
### OpenAI
|
||||
- **Imagens**: Máx 20 MB, até 10 imagens por requisição
|
||||
- **PDFs**: Máx 32 MB, até 100 páginas
|
||||
- **Áudio**: Máx 25 MB, até 25 minutos
|
||||
|
||||
### Anthropic
|
||||
- **Imagens**: Máx 5 MB, máx 8000x8000 pixels, até 100 imagens
|
||||
- **PDFs**: Máx 32 MB, até 100 páginas
|
||||
|
||||
### Google Gemini
|
||||
- **Imagens**: Máx 100 MB
|
||||
- **PDFs**: Máx 50 MB
|
||||
- **Áudio**: Máx 100 MB, até 9,5 horas
|
||||
- **Vídeo**: Máx 2 GB, até 1 hora
|
||||
|
||||
### AWS Bedrock
|
||||
- **Imagens**: Máx 4,5 MB, máx 8000x8000 pixels
|
||||
- **PDFs**: Máx 3,75 MB, até 100 páginas
|
||||
|
||||
## Referenciando Arquivos em Prompts
|
||||
|
||||
Use o nome da chave do arquivo nas descrições das suas tasks para referenciar arquivos:
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="""
|
||||
Analise os materiais fornecidos:
|
||||
1. Revise o gráfico em {sales_chart}
|
||||
2. Faça referência cruzada com dados em {quarterly_report}
|
||||
3. Resuma as principais descobertas
|
||||
""",
|
||||
expected_output="Resumo da análise com insights principais",
|
||||
input_files={
|
||||
"sales_chart": ImageFile(source="chart.png"),
|
||||
"quarterly_report": PDFFile(source="report.pdf"),
|
||||
}
|
||||
)
|
||||
```
|
||||
@@ -79,7 +79,7 @@ Existem diferentes locais no código do CrewAI onde você pode especificar o mod
|
||||
|
||||
# Configuração avançada com parâmetros detalhados
|
||||
llm = LLM(
|
||||
model="openai/gpt-4",
|
||||
model="openai/gpt-4",
|
||||
temperature=0.8,
|
||||
max_tokens=150,
|
||||
top_p=0.9,
|
||||
@@ -150,6 +150,37 @@ Nesta seção, você encontrará exemplos detalhados que ajudam a selecionar, co
|
||||
| o1-mini | 128.000 tokens | Raciocínio rápido, tarefas complexas |
|
||||
| o1-preview | 128.000 tokens | Raciocínio rápido, tarefas complexas |
|
||||
| o1 | 200.000 tokens | Raciocínio rápido, tarefas complexas |
|
||||
|
||||
**Responses API:**
|
||||
|
||||
A OpenAI oferece duas APIs: Chat Completions (padrão) e a nova Responses API. A Responses API foi projetada desde o início com suporte multimodal nativo—texto, imagens, áudio e chamadas de função são todos cidadãos de primeira classe. Ela oferece melhor performance com modelos de raciocínio e suporta recursos adicionais como auto-encadeamento e ferramentas integradas.
|
||||
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
# Usar Responses API em vez de Chat Completions
|
||||
llm = LLM(
|
||||
model="openai/gpt-4o",
|
||||
api="responses", # Habilitar Responses API
|
||||
store=True, # Armazenar respostas para multi-turno (opcional)
|
||||
auto_chain=True, # Auto-encadeamento para modelos de raciocínio (opcional)
|
||||
)
|
||||
```
|
||||
|
||||
**Parâmetros da Responses API:**
|
||||
- `api`: Defina como `"responses"` para usar a Responses API (padrão: `"completions"`)
|
||||
- `instructions`: Instruções de nível de sistema (apenas Responses API)
|
||||
- `store`: Se deve armazenar respostas para conversas multi-turno
|
||||
- `previous_response_id`: ID da resposta anterior para multi-turno
|
||||
- `include`: Dados adicionais para incluir na resposta (ex: `["reasoning.encrypted_content"]`)
|
||||
- `builtin_tools`: Lista de ferramentas integradas da OpenAI: `"web_search"`, `"file_search"`, `"code_interpreter"`, `"computer_use"`
|
||||
- `parse_tool_outputs`: Retornar `ResponsesAPIResult` estruturado com saídas de ferramentas integradas parseadas
|
||||
- `auto_chain`: Rastrear e usar automaticamente IDs de resposta para conversas multi-turno
|
||||
- `auto_chain_reasoning`: Rastrear itens de raciocínio criptografados para conformidade ZDR (Zero Data Retention)
|
||||
|
||||
<Tip>
|
||||
Use a Responses API para novos projetos, especialmente ao trabalhar com modelos de raciocínio (o1, o3, o4) ou quando precisar de suporte multimodal nativo para [arquivos](/pt-BR/concepts/files).
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Meta-Llama">
|
||||
@@ -207,11 +238,20 @@ Nesta seção, você encontrará exemplos detalhados que ajudam a selecionar, co
|
||||
Defina sua chave de API no seu arquivo `.env`. Se precisar de uma chave, ou encontrar uma existente, verifique o [AI Studio](https://aistudio.google.com/apikey).
|
||||
|
||||
```toml .env
|
||||
# https://ai.google.dev/gemini-api/docs/api-key
|
||||
# Para API Gemini (uma das seguintes)
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
GEMINI_API_KEY=<your-api-key>
|
||||
|
||||
# Para Vertex AI Express mode (autenticação por chave de API)
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
|
||||
# Para Vertex AI com conta de serviço
|
||||
GOOGLE_CLOUD_PROJECT=<your-project-id>
|
||||
GOOGLE_CLOUD_LOCATION=<location> # Padrão: us-central1
|
||||
```
|
||||
|
||||
Exemplo de uso em seu projeto CrewAI:
|
||||
**Uso Básico:**
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
@@ -221,6 +261,34 @@ Nesta seção, você encontrará exemplos detalhados que ajudam a selecionar, co
|
||||
)
|
||||
```
|
||||
|
||||
**Vertex AI Express Mode (Autenticação por Chave de API):**
|
||||
|
||||
O Vertex AI Express mode permite usar o Vertex AI com autenticação simples por chave de API, em vez de credenciais de conta de serviço. Esta é a maneira mais rápida de começar com o Vertex AI.
|
||||
|
||||
Para habilitar o Express mode, defina ambas as variáveis de ambiente no seu arquivo `.env`:
|
||||
```toml .env
|
||||
GOOGLE_GENAI_USE_VERTEXAI=true
|
||||
GOOGLE_API_KEY=<your-api-key>
|
||||
```
|
||||
|
||||
Em seguida, use o LLM normalmente:
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
llm = LLM(
|
||||
model="gemini/gemini-2.0-flash",
|
||||
temperature=0.7
|
||||
)
|
||||
```
|
||||
|
||||
<Info>
|
||||
Para obter uma chave de API do Express mode:
|
||||
- Novos usuários do Google Cloud: Obtenha uma [chave de API do Express mode](https://cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey)
|
||||
- Usuários existentes do Google Cloud: Obtenha uma [chave de API do Google Cloud vinculada a uma conta de serviço](https://cloud.google.com/docs/authentication/api-keys)
|
||||
|
||||
Para mais detalhes, consulte a [documentação do Vertex AI Express mode](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/start/quickstart?usertype=apikey).
|
||||
</Info>
|
||||
|
||||
### Modelos Gemini
|
||||
|
||||
O Google oferece uma variedade de modelos poderosos otimizados para diferentes casos de uso.
|
||||
@@ -823,7 +891,7 @@ Saiba como obter o máximo da configuração do seu LLM:
|
||||
Lembre-se de monitorar regularmente o uso de tokens e ajustar suas configurações para otimizar custos e desempenho.
|
||||
</Info>
|
||||
</Accordion>
|
||||
|
||||
|
||||
<Accordion title="Descartar Parâmetros Adicionais">
|
||||
O CrewAI usa Litellm internamente para chamadas LLM, permitindo descartar parâmetros adicionais desnecessários para seu caso de uso. Isso pode simplificar seu código e reduzir a complexidade da configuração do LLM.
|
||||
Por exemplo, se não precisar enviar o parâmetro <code>stop</code>, basta omiti-lo na chamada do LLM:
|
||||
@@ -882,4 +950,4 @@ Saiba como obter o máximo da configuração do seu LLM:
|
||||
llm = LLM(model="openai/gpt-4o") # 128K tokens
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Tabs>
|
||||
|
||||
@@ -128,7 +128,7 @@ Ao implantar seu Flow, considere o seguinte:
|
||||
### CrewAI Enterprise
|
||||
A maneira mais fácil de implantar seu Flow é usando o CrewAI Enterprise. Ele lida com a infraestrutura, autenticação e monitoramento para você.
|
||||
|
||||
Confira o [Guia de Implantação](/pt-BR/enterprise/guides/deploy-crew) para começar.
|
||||
Confira o [Guia de Implantação](/pt-BR/enterprise/guides/deploy-to-amp) para começar.
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
|
||||
@@ -91,7 +91,7 @@ Após implantar, você pode ver os detalhes da automação e usar o menu **Optio
|
||||
## Relacionados
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Implantar um Crew" href="/pt-BR/enterprise/guides/deploy-crew" icon="rocket">
|
||||
<Card title="Implantar um Crew" href="/pt-BR/enterprise/guides/deploy-to-amp" icon="rocket">
|
||||
Implante um Crew via GitHub ou arquivo ZIP.
|
||||
</Card>
|
||||
<Card title="Gatilhos de Automação" href="/pt-BR/enterprise/guides/automation-triggers" icon="trigger">
|
||||
|
||||
@@ -79,7 +79,7 @@ Após publicar, você pode visualizar os detalhes da automação e usar o menu *
|
||||
<Card title="Criar um Crew" href="/pt-BR/enterprise/guides/build-crew" icon="paintbrush">
|
||||
Crie um Crew.
|
||||
</Card>
|
||||
<Card title="Implantar um Crew" href="/pt-BR/enterprise/guides/deploy-crew" icon="rocket">
|
||||
<Card title="Implantar um Crew" href="/pt-BR/enterprise/guides/deploy-to-amp" icon="rocket">
|
||||
Implante um Crew via GitHub ou ZIP.
|
||||
</Card>
|
||||
<Card title="Exportar um Componente React" href="/pt-BR/enterprise/guides/react-component-export" icon="download">
|
||||
|
||||
563
docs/pt-BR/enterprise/features/flow-hitl-management.mdx
Normal file
@@ -0,0 +1,563 @@
|
||||
---
|
||||
title: "Gerenciamento HITL para Flows"
|
||||
description: "Revisão humana de nível empresarial para Flows com notificações por email, regras de roteamento e capacidades de resposta automática"
|
||||
icon: "users-gear"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Os recursos de gerenciamento HITL para Flows requerem o decorador `@human_feedback`, disponível no **CrewAI versão 1.8.0 ou superior**. Estes recursos aplicam-se especificamente a **Flows**, não a Crews.
|
||||
</Note>
|
||||
|
||||
O CrewAI Enterprise oferece um sistema abrangente de gerenciamento Human-in-the-Loop (HITL) para Flows que transforma fluxos de trabalho de IA em processos colaborativos humano-IA. A plataforma usa uma **arquitetura email-first** que permite que qualquer pessoa com um endereço de email responda a solicitações de revisão—sem necessidade de conta na plataforma.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Design Email-First" icon="envelope">
|
||||
Respondentes podem responder diretamente aos emails de notificação para fornecer feedback
|
||||
</Card>
|
||||
<Card title="Roteamento Flexível" icon="route">
|
||||
Direcione solicitações para emails específicos com base em padrões de método ou estado do flow
|
||||
</Card>
|
||||
<Card title="Resposta Automática" icon="clock">
|
||||
Configure respostas automáticas de fallback quando nenhum humano responder a tempo
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Principais Benefícios
|
||||
|
||||
- **Modelo mental simples**: Endereços de email são universais; não é necessário gerenciar usuários ou funções da plataforma
|
||||
- **Respondentes externos**: Qualquer pessoa com email pode responder, mesmo não sendo usuário da plataforma
|
||||
- **Atribuição dinâmica**: Obtenha o email do responsável diretamente do estado do flow (ex: `sales_rep_email`)
|
||||
- **Configuração reduzida**: Menos configurações para definir, tempo mais rápido para gerar valor
|
||||
- **Email como canal principal**: A maioria dos usuários prefere responder via email do que fazer login em um dashboard
|
||||
|
||||
## Configurando Pontos de Revisão Humana em Flows
|
||||
|
||||
Configure checkpoints de revisão humana em seus Flows usando o decorador `@human_feedback`. Quando a execução atinge um ponto de revisão, o sistema pausa, notifica o responsável via email e aguarda uma resposta.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start, listen
|
||||
from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult
|
||||
|
||||
class ContentApprovalFlow(Flow):
|
||||
@start()
|
||||
def generate_content(self):
|
||||
# IA gera conteúdo
|
||||
return "Texto de marketing gerado para campanha Q1..."
|
||||
|
||||
@listen(generate_content)
|
||||
@human_feedback(
|
||||
message="Por favor, revise este conteúdo para conformidade com a marca:",
|
||||
emit=["approved", "rejected", "needs_revision"],
|
||||
)
|
||||
def review_content(self, content):
|
||||
return content
|
||||
|
||||
@listen("approved")
|
||||
def publish_content(self, result: HumanFeedbackResult):
|
||||
print(f"Publicando conteúdo aprovado. Notas do revisor: {result.feedback}")
|
||||
|
||||
@listen("rejected")
|
||||
def archive_content(self, result: HumanFeedbackResult):
|
||||
print(f"Conteúdo rejeitado. Motivo: {result.feedback}")
|
||||
|
||||
@listen("needs_revision")
|
||||
def revise_content(self, result: HumanFeedbackResult):
|
||||
print(f"Revisão solicitada: {result.feedback}")
|
||||
```
|
||||
|
||||
Para detalhes completos de implementação, consulte o guia [Feedback Humano em Flows](/pt-BR/learn/human-feedback-in-flows).
|
||||
|
||||
### Parâmetros do Decorador
|
||||
|
||||
| Parâmetro | Tipo | Descrição |
|
||||
|-----------|------|-----------|
|
||||
| `message` | `str` | A mensagem exibida para o revisor humano |
|
||||
| `emit` | `list[str]` | Opções de resposta válidas (exibidas como botões na UI) |
|
||||
|
||||
## Configuração da Plataforma
|
||||
|
||||
Acesse a configuração HITL em: **Deployment** → **Settings** → **Human in the Loop Configuration**
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-overview.png" alt="Configurações HITL" />
|
||||
</Frame>
|
||||
|
||||
### Notificações por Email
|
||||
|
||||
Toggle para ativar ou desativar notificações por email para solicitações HITL.
|
||||
|
||||
| Configuração | Padrão | Descrição |
|
||||
|--------------|--------|-----------|
|
||||
| Notificações por Email | Ativado | Enviar emails quando feedback for solicitado |
|
||||
|
||||
<Note>
|
||||
Quando desativado, os respondentes devem usar a UI do dashboard ou você deve configurar webhooks para sistemas de notificação personalizados.
|
||||
</Note>
|
||||
|
||||
### Meta de SLA
|
||||
|
||||
Defina um tempo de resposta alvo para fins de rastreamento e métricas.
|
||||
|
||||
| Configuração | Descrição |
|
||||
|--------------|-----------|
|
||||
| Meta de SLA (minutos) | Tempo de resposta alvo. Usado para métricas do dashboard e rastreamento de SLA |
|
||||
|
||||
Deixe vazio para desativar o rastreamento de SLA.
|
||||
|
||||
## Notificações e Respostas por Email
|
||||
|
||||
O sistema HITL usa uma arquitetura email-first onde os respondentes podem responder diretamente aos emails de notificação.
|
||||
|
||||
### Como Funcionam as Respostas por Email
|
||||
|
||||
<Steps>
|
||||
<Step title="Notificação Enviada">
|
||||
Quando uma solicitação HITL é criada, um email é enviado ao respondente atribuído com o conteúdo e contexto da revisão.
|
||||
</Step>
|
||||
<Step title="Endereço Reply-To">
|
||||
O email inclui um endereço reply-to especial com um token assinado para autenticação.
|
||||
</Step>
|
||||
<Step title="Usuário Responde">
|
||||
O respondente simplesmente responde ao email com seu feedback—nenhum login necessário.
|
||||
</Step>
|
||||
<Step title="Validação do Token">
|
||||
A plataforma recebe a resposta, verifica o token assinado e corresponde o email do remetente.
|
||||
</Step>
|
||||
<Step title="Flow Continua">
|
||||
O feedback é registrado e o flow continua com a entrada humana.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Formato de Resposta
|
||||
|
||||
Respondentes podem responder com:
|
||||
|
||||
- **Opção emit**: Se a resposta corresponder a uma opção `emit` (ex: "approved"), ela é usada diretamente
|
||||
- **Texto livre**: Qualquer resposta de texto é passada para o flow como feedback
|
||||
- **Texto simples**: A primeira linha do corpo da resposta é usada como feedback
|
||||
|
||||
### Emails de Confirmação
|
||||
|
||||
Após processar uma resposta, o respondente recebe um email de confirmação indicando se o feedback foi enviado com sucesso ou se ocorreu um erro.
|
||||
|
||||
### Segurança do Token de Email
|
||||
|
||||
- Tokens são assinados criptograficamente para segurança
|
||||
- Tokens expiram após 7 dias
|
||||
- Email do remetente deve corresponder ao email autorizado do token
|
||||
- Emails de confirmação/erro são enviados após o processamento
|
||||
|
||||
## Regras de Roteamento
|
||||
|
||||
Direcione solicitações HITL para endereços de email específicos com base em padrões de método.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-routing-rules.png" alt="Configuração de Regras de Roteamento HITL" />
|
||||
</Frame>
|
||||
|
||||
### Estrutura da Regra
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Aprovações para Financeiro",
|
||||
"match": {
|
||||
"method_name": "approve_*"
|
||||
},
|
||||
"assign_to_email": "financeiro@empresa.com",
|
||||
"assign_from_input": "manager_email"
|
||||
}
|
||||
```
|
||||
|
||||
### Padrões de Correspondência
|
||||
|
||||
| Padrão | Descrição | Exemplo de Correspondência |
|
||||
|--------|-----------|---------------------------|
|
||||
| `approve_*` | Wildcard (qualquer caractere) | `approve_payment`, `approve_vendor` |
|
||||
| `review_?` | Caractere único | `review_a`, `review_1` |
|
||||
| `validate_payment` | Correspondência exata | apenas `validate_payment` |
|
||||
|
||||
### Prioridade de Atribuição
|
||||
|
||||
1. **Atribuição dinâmica** (`assign_from_input`): Se configurado, obtém email do estado do flow
|
||||
2. **Email estático** (`assign_to_email`): Fallback para email configurado
|
||||
3. **Criador do deployment**: Se nenhuma regra corresponder, o email do criador do deployment é usado
|
||||
|
||||
### Exemplo de Atribuição Dinâmica
|
||||
|
||||
Se seu estado do flow contém `{"sales_rep_email": "alice@empresa.com"}`, configure:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Direcionar para Representante de Vendas",
|
||||
"match": {
|
||||
"method_name": "review_*"
|
||||
},
|
||||
"assign_from_input": "sales_rep_email"
|
||||
}
|
||||
```
|
||||
|
||||
A solicitação será atribuída automaticamente para `alice@empresa.com`.
|
||||
|
||||
<Tip>
|
||||
**Caso de Uso**: Obtenha o responsável do seu CRM, banco de dados ou etapa anterior do flow para direcionar revisões dinamicamente para a pessoa certa.
|
||||
</Tip>
|
||||
|
||||
## Resposta Automática
|
||||
|
||||
Responda automaticamente a solicitações HITL se nenhum humano responder dentro do timeout. Isso garante que os flows não fiquem travados indefinidamente.
|
||||
|
||||
### Configuração
|
||||
|
||||
| Configuração | Descrição |
|
||||
|--------------|-----------|
|
||||
| Ativado | Toggle para ativar resposta automática |
|
||||
| Timeout (minutos) | Tempo de espera antes de responder automaticamente |
|
||||
| Resultado Padrão | O valor da resposta (deve corresponder a uma opção `emit`) |
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-auto-respond.png" alt="Configuração de Resposta Automática HITL" />
|
||||
</Frame>
|
||||
|
||||
### Casos de Uso
|
||||
|
||||
- **Conformidade com SLA**: Garante que flows não fiquem travados indefinidamente
|
||||
- **Aprovação padrão**: Aprove automaticamente solicitações de baixo risco após timeout
|
||||
- **Degradação graciosa**: Continue com um padrão seguro quando revisores não estiverem disponíveis
|
||||
|
||||
<Warning>
|
||||
Use resposta automática com cuidado. Ative apenas para revisões não críticas onde uma resposta padrão é aceitável.
|
||||
</Warning>
|
||||
|
||||
## Processo de Revisão
|
||||
|
||||
### Interface do Dashboard
|
||||
|
||||
A interface de revisão HITL oferece uma experiência limpa e focada para revisores:
|
||||
|
||||
- **Renderização Markdown**: Formatação rica para conteúdo de revisão com destaque de sintaxe
|
||||
- **Painel de Contexto**: Visualize estado do flow, histórico de execução e informações relacionadas
|
||||
- **Entrada de Feedback**: Forneça feedback detalhado e comentários com sua decisão
|
||||
- **Ações Rápidas**: Botões de opção emit com um clique com comentários opcionais
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-list-pending-feedbacks.png" alt="Lista de Solicitações HITL Pendentes" />
|
||||
</Frame>
|
||||
|
||||
### Métodos de Resposta
|
||||
|
||||
Revisores podem responder por três canais:
|
||||
|
||||
| Método | Descrição |
|
||||
|--------|-----------|
|
||||
| **Resposta por Email** | Responda diretamente ao email de notificação |
|
||||
| **Dashboard** | Use a UI do dashboard Enterprise |
|
||||
| **API/Webhook** | Resposta programática via API |
|
||||
|
||||
### Histórico e Trilha de Auditoria
|
||||
|
||||
Toda interação HITL é rastreada com uma linha do tempo completa:
|
||||
|
||||
- Histórico de decisões (aprovar/rejeitar/revisar)
|
||||
- Identidade do revisor e timestamp
|
||||
- Feedback e comentários fornecidos
|
||||
- Método de resposta (email/dashboard/API)
|
||||
- Métricas de tempo de resposta
|
||||
|
||||
## Análise e Monitoramento
|
||||
|
||||
Acompanhe o desempenho HITL com análises abrangentes.
|
||||
|
||||
### Dashboard de Desempenho
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-metrics.png" alt="Dashboard de Métricas HITL" />
|
||||
</Frame>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tempos de Resposta" icon="stopwatch">
|
||||
Monitore tempos de resposta médios e medianos por revisor ou flow.
|
||||
</Card>
|
||||
<Card title="Tendências de Volume" icon="chart-bar">
|
||||
Analise padrões de volume de revisão para otimizar capacidade da equipe.
|
||||
</Card>
|
||||
<Card title="Distribuição de Decisões" icon="chart-pie">
|
||||
Visualize taxas de aprovação/rejeição em diferentes tipos de revisão.
|
||||
</Card>
|
||||
<Card title="Rastreamento de SLA" icon="chart-line">
|
||||
Acompanhe a porcentagem de revisões concluídas dentro das metas de SLA.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Auditoria e Conformidade
|
||||
|
||||
Capacidades de auditoria prontas para empresas para requisitos regulatórios:
|
||||
|
||||
- Histórico completo de decisões com timestamps
|
||||
- Verificação de identidade do revisor
|
||||
- Logs de auditoria imutáveis
|
||||
- Capacidades de exportação para relatórios de conformidade
|
||||
|
||||
## Casos de Uso Comuns
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Revisões de Segurança" icon="shield-halved">
|
||||
**Caso de Uso**: Automação de questionários de segurança internos com validação humana
|
||||
|
||||
- IA gera respostas para questionários de segurança
|
||||
- Equipe de segurança revisa e valida precisão via email
|
||||
- Respostas aprovadas são compiladas na submissão final
|
||||
- Trilha de auditoria completa para conformidade
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Aprovação de Conteúdo" icon="file-lines">
|
||||
**Caso de Uso**: Conteúdo de marketing que requer revisão legal/marca
|
||||
|
||||
- IA gera texto de marketing ou conteúdo de mídia social
|
||||
- Roteie para email da equipe de marca para revisão de voz/tom
|
||||
- Publicação automática após aprovação
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Aprovações Financeiras" icon="money-bill">
|
||||
**Caso de Uso**: Relatórios de despesas, termos de contrato, alocações de orçamento
|
||||
|
||||
- IA pré-processa e categoriza solicitações financeiras
|
||||
- Roteie com base em limites de valor usando atribuição dinâmica
|
||||
- Mantenha trilha de auditoria completa para conformidade financeira
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Atribuição Dinâmica do CRM" icon="database">
|
||||
**Caso de Uso**: Direcione revisões para proprietários de conta do seu CRM
|
||||
|
||||
- Flow obtém email do proprietário da conta do CRM
|
||||
- Armazene email no estado do flow (ex: `account_owner_email`)
|
||||
- Use `assign_from_input` para direcionar automaticamente para a pessoa certa
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Garantia de Qualidade" icon="magnifying-glass">
|
||||
**Caso de Uso**: Validação de saída de IA antes da entrega ao cliente
|
||||
|
||||
- IA gera conteúdo ou respostas voltadas ao cliente
|
||||
- Equipe de QA revisa via notificação por email
|
||||
- Loops de feedback melhoram desempenho da IA ao longo do tempo
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## API de Webhooks
|
||||
|
||||
Quando seus Flows pausam para feedback humano, você pode configurar webhooks para enviar dados da solicitação para sua própria aplicação. Isso permite:
|
||||
|
||||
- Construir UIs de aprovação personalizadas
|
||||
- Integrar com ferramentas internas (Jira, ServiceNow, dashboards personalizados)
|
||||
- Rotear aprovações para sistemas de terceiros
|
||||
- Notificações em apps mobile
|
||||
- Sistemas de decisão automatizados
|
||||
|
||||
<Frame>
|
||||
<img src="/images/enterprise/hitl-settings-webhook.png" alt="Configuração de Webhook HITL" />
|
||||
</Frame>
|
||||
|
||||
### Configurando Webhooks
|
||||
|
||||
<Steps>
|
||||
<Step title="Navegue até Configurações">
|
||||
Vá para **Deployment** → **Settings** → **Human in the Loop**
|
||||
</Step>
|
||||
<Step title="Expanda a Seção Webhooks">
|
||||
Clique para expandir a configuração de **Webhooks**
|
||||
</Step>
|
||||
<Step title="Adicione sua URL de Webhook">
|
||||
Digite sua URL de webhook (deve ser HTTPS em produção)
|
||||
</Step>
|
||||
<Step title="Salve a Configuração">
|
||||
Clique em **Salvar Configuração** para ativar
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Você pode configurar múltiplos webhooks. Cada webhook ativo recebe todos os eventos HITL.
|
||||
|
||||
### Eventos de Webhook
|
||||
|
||||
Seu endpoint receberá requisições HTTP POST para estes eventos:
|
||||
|
||||
| Tipo de Evento | Quando é Disparado |
|
||||
|----------------|-------------------|
|
||||
| `new_request` | Um flow pausa e solicita feedback humano |
|
||||
|
||||
### Payload do Webhook
|
||||
|
||||
Todos os webhooks recebem um payload JSON com esta estrutura:
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "new_request",
|
||||
"request": {
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"flow_id": "flow_abc123",
|
||||
"method_name": "review_article",
|
||||
"message": "Por favor, revise este artigo para publicação.",
|
||||
"emit_options": ["approved", "rejected", "request_changes"],
|
||||
"state": {
|
||||
"article_id": 12345,
|
||||
"author": "john@example.com",
|
||||
"category": "technology"
|
||||
},
|
||||
"metadata": {},
|
||||
"created_at": "2026-01-14T12:00:00Z"
|
||||
},
|
||||
"deployment": {
|
||||
"id": 456,
|
||||
"name": "Content Review Flow",
|
||||
"organization_id": 789
|
||||
},
|
||||
"callback_url": "https://api.crewai.com/...",
|
||||
"assigned_to_email": "reviewer@company.com"
|
||||
}
|
||||
```
|
||||
|
||||
### Respondendo a Solicitações
|
||||
|
||||
Para enviar feedback, **faça POST para a `callback_url`** incluída no payload do webhook.
|
||||
|
||||
```http
|
||||
POST {callback_url}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"feedback": "Aprovado. Ótimo artigo!",
|
||||
"source": "my_custom_app"
|
||||
}
|
||||
```
|
||||
|
||||
### Segurança
|
||||
|
||||
<Info>
|
||||
Todas as requisições de webhook são assinadas criptograficamente usando HMAC-SHA256 para garantir autenticidade e prevenir adulteração.
|
||||
</Info>
|
||||
|
||||
#### Segurança do Webhook
|
||||
|
||||
- **Assinaturas HMAC-SHA256**: Todo webhook inclui uma assinatura criptográfica
|
||||
- **Secrets por webhook**: Cada webhook tem seu próprio secret de assinatura único
|
||||
- **Criptografado em repouso**: Os secrets de assinatura são criptografados no nosso banco de dados
|
||||
- **Verificação de timestamp**: Previne ataques de replay
|
||||
|
||||
#### Headers de Assinatura
|
||||
|
||||
Cada requisição de webhook inclui estes headers:
|
||||
|
||||
| Header | Descrição |
|
||||
|--------|-----------|
|
||||
| `X-Signature` | Assinatura HMAC-SHA256: `sha256=<hex_digest>` |
|
||||
| `X-Timestamp` | Timestamp Unix de quando a requisição foi assinada |
|
||||
|
||||
#### Verificação
|
||||
|
||||
Verifique computando:
|
||||
|
||||
```python
|
||||
import hmac
|
||||
import hashlib
|
||||
|
||||
expected = hmac.new(
|
||||
signing_secret.encode(),
|
||||
f"{timestamp}.{payload}".encode(),
|
||||
hashlib.sha256
|
||||
).hexdigest()
|
||||
|
||||
if hmac.compare_digest(expected, signature):
|
||||
# Assinatura válida
|
||||
```
|
||||
|
||||
### Tratamento de Erros
|
||||
|
||||
Seu endpoint de webhook deve retornar um código de status 2xx para confirmar o recebimento:
|
||||
|
||||
| Sua Resposta | Nosso Comportamento |
|
||||
|--------------|---------------------|
|
||||
| 2xx | Webhook entregue com sucesso |
|
||||
| 4xx/5xx | Registrado como falha, sem retry |
|
||||
| Timeout (30s) | Registrado como falha, sem retry |
|
||||
|
||||
## Segurança e RBAC
|
||||
|
||||
### Acesso ao Dashboard
|
||||
|
||||
O acesso HITL é controlado no nível do deployment:
|
||||
|
||||
| Permissão | Capacidade |
|
||||
|-----------|------------|
|
||||
| `manage_human_feedback` | Configurar settings HITL, ver todas as solicitações |
|
||||
| `respond_to_human_feedback` | Responder a solicitações, ver solicitações atribuídas |
|
||||
|
||||
### Autorização de Resposta por Email
|
||||
|
||||
Para respostas por email:
|
||||
1. O token reply-to codifica o email autorizado
|
||||
2. Email do remetente deve corresponder ao email do token
|
||||
3. Token não deve estar expirado (padrão 7 dias)
|
||||
4. Solicitação ainda deve estar pendente
|
||||
|
||||
### Trilha de Auditoria
|
||||
|
||||
Todas as ações HITL são registradas:
|
||||
- Criação de solicitação
|
||||
- Mudanças de atribuição
|
||||
- Submissão de resposta (com fonte: dashboard/email/API)
|
||||
- Status de retomada do flow
|
||||
|
||||
## Solução de Problemas
|
||||
|
||||
### Emails Não Enviando
|
||||
|
||||
1. Verifique se "Notificações por Email" está ativado na configuração
|
||||
2. Verifique se as regras de roteamento correspondem ao nome do método
|
||||
3. Verifique se o email do responsável é válido
|
||||
4. Verifique o fallback do criador do deployment se nenhuma regra de roteamento corresponder
|
||||
|
||||
### Respostas de Email Não Processando
|
||||
|
||||
1. Verifique se o token não expirou (padrão 7 dias)
|
||||
2. Verifique se o email do remetente corresponde ao email atribuído
|
||||
3. Garanta que a solicitação ainda está pendente (não respondida ainda)
|
||||
|
||||
### Flow Não Retomando
|
||||
|
||||
1. Verifique o status da solicitação no dashboard
|
||||
2. Verifique se a URL de callback está acessível
|
||||
3. Garanta que o deployment ainda está rodando
|
||||
|
||||
## Melhores Práticas
|
||||
|
||||
<Tip>
|
||||
**Comece Simples**: Comece com notificações por email para o criador do deployment, depois adicione regras de roteamento conforme seus fluxos de trabalho amadurecem.
|
||||
</Tip>
|
||||
|
||||
1. **Use Atribuição Dinâmica**: Obtenha emails de responsáveis do seu estado do flow para roteamento flexível.
|
||||
|
||||
2. **Configure Resposta Automática**: Defina um fallback para revisões não críticas para evitar que flows fiquem travados.
|
||||
|
||||
3. **Monitore Tempos de Resposta**: Use análises para identificar gargalos e otimizar seu processo de revisão.
|
||||
|
||||
4. **Mantenha Mensagens de Revisão Claras**: Escreva mensagens claras e acionáveis no decorador `@human_feedback`.
|
||||
|
||||
5. **Teste o Fluxo de Email**: Envie solicitações de teste para verificar a entrega de email antes de ir para produção.
|
||||
|
||||
## Recursos Relacionados
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Feedback Humano em Flows" icon="code" href="/pt-BR/learn/human-feedback-in-flows">
|
||||
Guia de implementação para o decorador `@human_feedback`
|
||||
</Card>
|
||||
<Card title="Guia de Workflow HITL para Flows" icon="route" href="/pt-BR/enterprise/guides/human-in-the-loop">
|
||||
Guia passo a passo para configurar workflows HITL
|
||||
</Card>
|
||||
<Card title="Configuração RBAC" icon="shield-check" href="/pt-BR/enterprise/features/rbac">
|
||||
Configure controle de acesso baseado em função para sua organização
|
||||
</Card>
|
||||
<Card title="Streaming de Webhook" icon="bolt" href="/pt-BR/enterprise/features/webhook-streaming">
|
||||
Configure notificações de eventos em tempo real
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,304 +0,0 @@
|
||||
---
|
||||
title: "Deploy Crew"
|
||||
description: "Implantando um Crew na CrewAI AMP"
|
||||
icon: "rocket"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Depois de criar um crew localmente ou pelo Crew Studio, o próximo passo é
|
||||
implantá-lo na plataforma CrewAI AMP. Este guia cobre múltiplos métodos de
|
||||
implantação para ajudá-lo a escolher a melhor abordagem para o seu fluxo de
|
||||
trabalho.
|
||||
</Note>
|
||||
|
||||
## Pré-requisitos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Crew Pronto para Implantação" icon="users">
|
||||
Você deve ter um crew funcional, criado localmente ou pelo Crew Studio
|
||||
</Card>
|
||||
<Card title="Repositório GitHub" icon="github">
|
||||
O código do seu crew deve estar em um repositório do GitHub (para o método
|
||||
de integração com GitHub)
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Opção 1: Implantar Usando o CrewAI CLI
|
||||
|
||||
A CLI fornece a maneira mais rápida de implantar crews desenvolvidos localmente na plataforma Enterprise.
|
||||
|
||||
<Steps>
|
||||
<Step title="Instale o CrewAI CLI">
|
||||
Se ainda não tiver, instale o CrewAI CLI:
|
||||
|
||||
```bash
|
||||
pip install crewai[tools]
|
||||
```
|
||||
|
||||
<Tip>
|
||||
A CLI vem com o pacote principal CrewAI, mas o extra `[tools]` garante todas as dependências de implantação.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Autentique-se na Plataforma Enterprise">
|
||||
Primeiro, você precisa autenticar sua CLI com a plataforma CrewAI AMP:
|
||||
|
||||
```bash
|
||||
# Se já possui uma conta CrewAI AMP, ou deseja criar uma:
|
||||
crewai login
|
||||
```
|
||||
|
||||
Ao executar qualquer um dos comandos, a CLI irá:
|
||||
1. Exibir uma URL e um código de dispositivo único
|
||||
2. Abrir seu navegador para a página de autenticação
|
||||
3. Solicitar a confirmação do dispositivo
|
||||
4. Completar o processo de autenticação
|
||||
|
||||
Após a autenticação bem-sucedida, você verá uma mensagem de confirmação no terminal!
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Criar uma Implantação">
|
||||
|
||||
No diretório do seu projeto, execute:
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
```
|
||||
|
||||
Este comando irá:
|
||||
1. Detectar informações do seu repositório GitHub
|
||||
2. Identificar variáveis de ambiente no seu arquivo `.env` local
|
||||
3. Transferir essas variáveis com segurança para a plataforma Enterprise
|
||||
4. Criar uma nova implantação com um identificador único
|
||||
|
||||
Com a criação bem-sucedida, você verá uma mensagem como:
|
||||
```shell
|
||||
Deployment created successfully!
|
||||
Name: your_project_name
|
||||
Deployment ID: 01234567-89ab-cdef-0123-456789abcdef
|
||||
Current Status: Deploy Enqueued
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Acompanhe o Progresso da Implantação">
|
||||
|
||||
Acompanhe o status da implantação com:
|
||||
|
||||
```bash
|
||||
crewai deploy status
|
||||
```
|
||||
|
||||
Para ver logs detalhados do processo de build:
|
||||
|
||||
```bash
|
||||
crewai deploy logs
|
||||
```
|
||||
|
||||
<Tip>
|
||||
A primeira implantação normalmente leva de 10 a 15 minutos, pois as imagens dos containers são construídas. As próximas implantações são bem mais rápidas.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Comandos Adicionais da CLI
|
||||
|
||||
O CrewAI CLI oferece vários comandos para gerenciar suas implantações:
|
||||
|
||||
```bash
|
||||
# Liste todas as suas implantações
|
||||
crewai deploy list
|
||||
|
||||
# Consulte o status de uma implantação
|
||||
crewai deploy status
|
||||
|
||||
# Veja os logs da implantação
|
||||
crewai deploy logs
|
||||
|
||||
# Envie atualizações após alterações no código
|
||||
crewai deploy push
|
||||
|
||||
# Remova uma implantação
|
||||
crewai deploy remove <deployment_id>
|
||||
```
|
||||
|
||||
## Opção 2: Implantar Diretamente pela Interface Web
|
||||
|
||||
Você também pode implantar seus crews diretamente pela interface web da CrewAI AMP conectando sua conta do GitHub. Esta abordagem não requer utilizar a CLI na sua máquina local.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Enviar no GitHub">
|
||||
|
||||
Você precisa subir seu crew para um repositório do GitHub. Caso ainda não tenha criado um crew, você pode [seguir este tutorial](/pt-BR/quickstart).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Conectando o GitHub ao CrewAI AMP">
|
||||
|
||||
1. Faça login em [CrewAI AMP](https://app.crewai.com)
|
||||
2. Clique no botão "Connect GitHub"
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Selecionar o Repositório">
|
||||
|
||||
Após conectar sua conta GitHub, você poderá selecionar qual repositório deseja implantar:
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Definir as Variáveis de Ambiente">
|
||||
|
||||
Antes de implantar, você precisará configurar as variáveis de ambiente para conectar ao seu provedor de LLM ou outros serviços:
|
||||
|
||||
1. Você pode adicionar variáveis individualmente ou em lote
|
||||
2. Digite suas variáveis no formato `KEY=VALUE` (uma por linha)
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Implante Seu Crew">
|
||||
|
||||
1. Clique no botão "Deploy" para iniciar o processo de implantação
|
||||
2. Você pode monitorar o progresso pela barra de progresso
|
||||
3. A primeira implantação geralmente demora de 10 a 15 minutos; as próximas serão mais rápidas
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
Após a conclusão, você verá:
|
||||
- A URL exclusiva do seu crew
|
||||
- Um Bearer token para proteger sua API crew
|
||||
- Um botão "Delete" caso precise remover a implantação
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## ⚠️ Requisitos de Segurança para Variáveis de Ambiente
|
||||
|
||||
<Warning>
|
||||
**Importante**: A CrewAI AMP possui restrições de segurança sobre os nomes de
|
||||
variáveis de ambiente que podem causar falha na implantação caso não sejam
|
||||
seguidas.
|
||||
</Warning>
|
||||
|
||||
### Padrões de Variáveis de Ambiente Bloqueados
|
||||
|
||||
Por motivos de segurança, os seguintes padrões de nome de variável de ambiente são **automaticamente filtrados** e causarão problemas de implantação:
|
||||
|
||||
**Padrões Bloqueados:**
|
||||
|
||||
- Variáveis terminando em `_TOKEN` (ex: `MY_API_TOKEN`)
|
||||
- Variáveis terminando em `_PASSWORD` (ex: `DB_PASSWORD`)
|
||||
- Variáveis terminando em `_SECRET` (ex: `API_SECRET`)
|
||||
- Variáveis terminando em `_KEY` em certos contextos
|
||||
|
||||
**Variáveis Bloqueadas Específicas:**
|
||||
|
||||
- `GITHUB_USER`, `GITHUB_TOKEN`
|
||||
- `AWS_REGION`, `AWS_DEFAULT_REGION`
|
||||
- Diversas variáveis internas do sistema CrewAI
|
||||
|
||||
### Exceções Permitidas
|
||||
|
||||
Algumas variáveis são explicitamente permitidas mesmo coincidindo com os padrões bloqueados:
|
||||
|
||||
- `AZURE_AD_TOKEN`
|
||||
- `AZURE_OPENAI_AD_TOKEN`
|
||||
- `ENTERPRISE_ACTION_TOKEN`
|
||||
- `CREWAI_ENTEPRISE_TOOLS_TOKEN`
|
||||
|
||||
### Como Corrigir Problemas de Nomeação
|
||||
|
||||
Se sua implantação falhar devido a restrições de variáveis de ambiente:
|
||||
|
||||
```bash
|
||||
# ❌ Estas irão causar falhas na implantação
|
||||
OPENAI_TOKEN=sk-...
|
||||
DATABASE_PASSWORD=mysenha
|
||||
API_SECRET=segredo123
|
||||
|
||||
# ✅ Utilize estes padrões de nomeação
|
||||
OPENAI_API_KEY=sk-...
|
||||
DATABASE_CREDENTIALS=mysenha
|
||||
API_CONFIG=segredo123
|
||||
```
|
||||
|
||||
### Melhores Práticas
|
||||
|
||||
1. **Use convenções padrão de nomenclatura**: `PROVIDER_API_KEY` em vez de `PROVIDER_TOKEN`
|
||||
2. **Teste localmente primeiro**: Certifique-se de que seu crew funciona com as variáveis renomeadas
|
||||
3. **Atualize seu código**: Altere todas as referências aos nomes antigos das variáveis
|
||||
4. **Documente as mudanças**: Mantenha registro das variáveis renomeadas para seu time
|
||||
|
||||
<Tip>
|
||||
Se você se deparar com falhas de implantação com erros enigmáticos de
|
||||
variáveis de ambiente, confira primeiro os nomes das variáveis em relação a
|
||||
esses padrões.
|
||||
</Tip>
|
||||
|
||||
### Interaja com Seu Crew Implantado
|
||||
|
||||
Após a implantação, você pode acessar seu crew por meio de:
|
||||
|
||||
1. **REST API**: A plataforma gera um endpoint HTTPS exclusivo com estas rotas principais:
|
||||
|
||||
- `/inputs`: Lista os parâmetros de entrada requeridos
|
||||
- `/kickoff`: Inicia uma execução com os inputs fornecidos
|
||||
- `/status/{kickoff_id}`: Consulta o status da execução
|
||||
|
||||
2. **Interface Web**: Acesse [app.crewai.com](https://app.crewai.com) para visualizar:
|
||||
- **Aba Status**: Informações da implantação, detalhes do endpoint da API e token de autenticação
|
||||
- **Aba Run**: Visualização da estrutura do seu crew
|
||||
- **Aba Executions**: Histórico de todas as execuções
|
||||
- **Aba Metrics**: Análises de desempenho
|
||||
- **Aba Traces**: Insights detalhados das execuções
|
||||
|
||||
### Dispare uma Execução
|
||||
|
||||
No dashboard Enterprise, você pode:
|
||||
|
||||
1. Clicar no nome do seu crew para abrir seus detalhes
|
||||
2. Selecionar "Trigger Crew" na interface de gerenciamento
|
||||
3. Inserir os inputs necessários no modal exibido
|
||||
4. Monitorar o progresso à medida que a execução avança pelo pipeline
|
||||
|
||||
### Monitoramento e Análises
|
||||
|
||||
A plataforma Enterprise oferece recursos abrangentes de observabilidade:
|
||||
|
||||
- **Gestão das Execuções**: Acompanhe execuções ativas e concluídas
|
||||
- **Traces**: Quebra detalhada de cada execução
|
||||
- **Métricas**: Uso de tokens, tempos de execução e custos
|
||||
- **Visualização em Linha do Tempo**: Representação visual das sequências de tarefas
|
||||
|
||||
### Funcionalidades Avançadas
|
||||
|
||||
A plataforma Enterprise também oferece:
|
||||
|
||||
- **Gerenciamento de Variáveis de Ambiente**: Armazene e gerencie com segurança as chaves de API
|
||||
- **Conexões com LLM**: Configure integrações com diversos provedores de LLM
|
||||
- **Repositório Custom Tools**: Crie, compartilhe e instale ferramentas
|
||||
- **Crew Studio**: Monte crews via interface de chat sem escrever código
|
||||
|
||||
<Card title="Precisa de Ajuda?" icon="headset" href="mailto:support@crewai.com">
|
||||
Entre em contato com nossa equipe de suporte para ajuda com questões de
|
||||
implantação ou dúvidas sobre a plataforma Enterprise.
|
||||
</Card>
|
||||
439
docs/pt-BR/enterprise/guides/deploy-to-amp.mdx
Normal file
@@ -0,0 +1,439 @@
|
||||
---
|
||||
title: "Deploy para AMP"
|
||||
description: "Implante seu Crew ou Flow no CrewAI AMP"
|
||||
icon: "rocket"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Depois de criar um Crew ou Flow localmente (ou pelo Crew Studio), o próximo passo é
|
||||
implantá-lo na plataforma CrewAI AMP. Este guia cobre múltiplos métodos de
|
||||
implantação para ajudá-lo a escolher a melhor abordagem para o seu fluxo de trabalho.
|
||||
</Note>
|
||||
|
||||
## Pré-requisitos
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Projeto Pronto para Implantação" icon="check-circle">
|
||||
Você deve ter um Crew ou Flow funcionando localmente com sucesso.
|
||||
Siga nosso [guia de preparação](/pt-BR/enterprise/guides/prepare-for-deployment) para verificar a estrutura do seu projeto.
|
||||
</Card>
|
||||
<Card title="Repositório GitHub" icon="github">
|
||||
Seu código deve estar em um repositório do GitHub (para o método de integração com GitHub).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Info>
|
||||
**Crews vs Flows**: Ambos os tipos de projeto podem ser implantados como "automações" no CrewAI AMP.
|
||||
O processo de implantação é o mesmo, mas eles têm estruturas de projeto diferentes.
|
||||
Veja [Preparar para Implantação](/pt-BR/enterprise/guides/prepare-for-deployment) para detalhes.
|
||||
</Info>
|
||||
|
||||
## Opção 1: Implantar Usando o CrewAI CLI
|
||||
|
||||
A CLI fornece a maneira mais rápida de implantar Crews ou Flows desenvolvidos localmente na plataforma AMP.
|
||||
A CLI detecta automaticamente o tipo do seu projeto a partir do `pyproject.toml` e faz o build adequadamente.
|
||||
|
||||
<Steps>
|
||||
<Step title="Instale o CrewAI CLI">
|
||||
Se ainda não tiver, instale o CrewAI CLI:
|
||||
|
||||
```bash
|
||||
pip install crewai[tools]
|
||||
```
|
||||
|
||||
<Tip>
|
||||
A CLI vem com o pacote principal CrewAI, mas o extra `[tools]` garante todas as dependências de implantação.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Autentique-se na Plataforma Enterprise">
|
||||
Primeiro, você precisa autenticar sua CLI com a plataforma CrewAI AMP:
|
||||
|
||||
```bash
|
||||
# Se já possui uma conta CrewAI AMP, ou deseja criar uma:
|
||||
crewai login
|
||||
```
|
||||
|
||||
Ao executar qualquer um dos comandos, a CLI irá:
|
||||
1. Exibir uma URL e um código de dispositivo único
|
||||
2. Abrir seu navegador para a página de autenticação
|
||||
3. Solicitar a confirmação do dispositivo
|
||||
4. Completar o processo de autenticação
|
||||
|
||||
Após a autenticação bem-sucedida, você verá uma mensagem de confirmação no terminal!
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Criar uma Implantação">
|
||||
|
||||
No diretório do seu projeto, execute:
|
||||
|
||||
```bash
|
||||
crewai deploy create
|
||||
```
|
||||
|
||||
Este comando irá:
|
||||
1. Detectar informações do seu repositório GitHub
|
||||
2. Identificar variáveis de ambiente no seu arquivo `.env` local
|
||||
3. Transferir essas variáveis com segurança para a plataforma Enterprise
|
||||
4. Criar uma nova implantação com um identificador único
|
||||
|
||||
Com a criação bem-sucedida, você verá uma mensagem como:
|
||||
```shell
|
||||
Deployment created successfully!
|
||||
Name: your_project_name
|
||||
Deployment ID: 01234567-89ab-cdef-0123-456789abcdef
|
||||
Current Status: Deploy Enqueued
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Acompanhe o Progresso da Implantação">
|
||||
|
||||
Acompanhe o status da implantação com:
|
||||
|
||||
```bash
|
||||
crewai deploy status
|
||||
```
|
||||
|
||||
Para ver logs detalhados do processo de build:
|
||||
|
||||
```bash
|
||||
crewai deploy logs
|
||||
```
|
||||
|
||||
<Tip>
|
||||
A primeira implantação normalmente leva de 10 a 15 minutos, pois as imagens dos containers são construídas. As próximas implantações são bem mais rápidas.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Comandos Adicionais da CLI
|
||||
|
||||
O CrewAI CLI oferece vários comandos para gerenciar suas implantações:
|
||||
|
||||
```bash
|
||||
# Liste todas as suas implantações
|
||||
crewai deploy list
|
||||
|
||||
# Consulte o status de uma implantação
|
||||
crewai deploy status
|
||||
|
||||
# Veja os logs da implantação
|
||||
crewai deploy logs
|
||||
|
||||
# Envie atualizações após alterações no código
|
||||
crewai deploy push
|
||||
|
||||
# Remova uma implantação
|
||||
crewai deploy remove <deployment_id>
|
||||
```
|
||||
|
||||
## Opção 2: Implantar Diretamente pela Interface Web
|
||||
|
||||
Você também pode implantar seus Crews ou Flows diretamente pela interface web do CrewAI AMP conectando sua conta do GitHub. Esta abordagem não requer utilizar a CLI na sua máquina local. A plataforma detecta automaticamente o tipo do seu projeto e trata o build adequadamente.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Enviar para o GitHub">
|
||||
|
||||
Você precisa enviar seu crew para um repositório do GitHub. Caso ainda não tenha criado um crew, você pode [seguir este tutorial](/pt-BR/quickstart).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Conectando o GitHub ao CrewAI AMP">
|
||||
|
||||
1. Faça login em [CrewAI AMP](https://app.crewai.com)
|
||||
2. Clique no botão "Connect GitHub"
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Selecionar o Repositório">
|
||||
|
||||
Após conectar sua conta GitHub, você poderá selecionar qual repositório deseja implantar:
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Definir as Variáveis de Ambiente">
|
||||
|
||||
Antes de implantar, você precisará configurar as variáveis de ambiente para conectar ao seu provedor de LLM ou outros serviços:
|
||||
|
||||
1. Você pode adicionar variáveis individualmente ou em lote
|
||||
2. Digite suas variáveis no formato `KEY=VALUE` (uma por linha)
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Implante Seu Crew">
|
||||
|
||||
1. Clique no botão "Deploy" para iniciar o processo de implantação
|
||||
2. Você pode monitorar o progresso pela barra de progresso
|
||||
3. A primeira implantação geralmente demora de 10 a 15 minutos; as próximas serão mais rápidas
|
||||
|
||||
<Frame>
|
||||

|
||||
</Frame>
|
||||
|
||||
Após a conclusão, você verá:
|
||||
- A URL exclusiva do seu crew
|
||||
- Um Bearer token para proteger sua API crew
|
||||
- Um botão "Delete" caso precise remover a implantação
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Opção 3: Reimplantar Usando API (Integração CI/CD)
|
||||
|
||||
Para implantações automatizadas em pipelines CI/CD, você pode usar a API do CrewAI para acionar reimplantações de crews existentes. Isso é particularmente útil para GitHub Actions, Jenkins ou outros workflows de automação.
|
||||
|
||||
<Steps>
|
||||
<Step title="Obtenha Seu Token de Acesso Pessoal">
|
||||
|
||||
Navegue até as configurações da sua conta CrewAI AMP para gerar um token de API:
|
||||
|
||||
1. Acesse [app.crewai.com](https://app.crewai.com)
|
||||
2. Clique em **Settings** → **Account** → **Personal Access Token**
|
||||
3. Gere um novo token e copie-o com segurança
|
||||
4. Armazene este token como um secret no seu sistema CI/CD
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Encontre o UUID da Sua Automação">
|
||||
|
||||
Localize o identificador único do seu crew implantado:
|
||||
|
||||
1. Acesse **Automations** no seu dashboard CrewAI AMP
|
||||
2. Selecione sua automação/crew existente
|
||||
3. Clique em **Additional Details**
|
||||
4. Copie o **UUID** - este identifica sua implantação específica do crew
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Acione a Reimplantação via API">
|
||||
|
||||
Use o endpoint da API de Deploy para acionar uma reimplantação:
|
||||
|
||||
```bash
|
||||
curl -i -X POST \
|
||||
-H "Authorization: Bearer YOUR_PERSONAL_ACCESS_TOKEN" \
|
||||
https://app.crewai.com/crewai_plus/api/v1/crews/YOUR-AUTOMATION-UUID/deploy
|
||||
|
||||
# HTTP/2 200
|
||||
# content-type: application/json
|
||||
#
|
||||
# {
|
||||
# "uuid": "your-automation-uuid",
|
||||
# "status": "Deploy Enqueued",
|
||||
# "public_url": "https://your-crew-deployment.crewai.com",
|
||||
# "token": "your-bearer-token"
|
||||
# }
|
||||
```
|
||||
|
||||
<Info>
|
||||
Se sua automação foi criada originalmente conectada ao Git, a API automaticamente puxará as últimas alterações do seu repositório antes de reimplantar.
|
||||
</Info>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Exemplo de Integração com GitHub Actions">
|
||||
|
||||
Aqui está um workflow do GitHub Actions com gatilhos de implantação mais complexos:
|
||||
|
||||
```yaml
|
||||
name: Deploy CrewAI Automation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
types: [ labeled ]
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy')) ||
|
||||
(github.event_name == 'release')
|
||||
steps:
|
||||
- name: Trigger CrewAI Redeployment
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer ${{ secrets.CREWAI_PAT }}" \
|
||||
https://app.crewai.com/crewai_plus/api/v1/crews/${{ secrets.CREWAI_AUTOMATION_UUID }}/deploy
|
||||
```
|
||||
|
||||
<Tip>
|
||||
Adicione `CREWAI_PAT` e `CREWAI_AUTOMATION_UUID` como secrets do repositório. Para implantações de PR, adicione um label "deploy" para acionar o workflow.
|
||||
</Tip>
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Interaja com Sua Automação Implantada
|
||||
|
||||
Após a implantação, você pode acessar seu crew através de:
|
||||
|
||||
1. **REST API**: A plataforma gera um endpoint HTTPS exclusivo com estas rotas principais:
|
||||
|
||||
- `/inputs`: Lista os parâmetros de entrada requeridos
|
||||
- `/kickoff`: Inicia uma execução com os inputs fornecidos
|
||||
- `/status/{kickoff_id}`: Consulta o status da execução
|
||||
|
||||
2. **Interface Web**: Acesse [app.crewai.com](https://app.crewai.com) para visualizar:
|
||||
- **Aba Status**: Informações da implantação, detalhes do endpoint da API e token de autenticação
|
||||
- **Aba Run**: Visualização da estrutura do seu crew
|
||||
- **Aba Executions**: Histórico de todas as execuções
|
||||
- **Aba Metrics**: Análises de desempenho
|
||||
- **Aba Traces**: Insights detalhados das execuções
|
||||
|
||||
### Dispare uma Execução
|
||||
|
||||
No dashboard Enterprise, você pode:
|
||||
|
||||
1. Clicar no nome do seu crew para abrir seus detalhes
|
||||
2. Selecionar "Trigger Crew" na interface de gerenciamento
|
||||
3. Inserir os inputs necessários no modal exibido
|
||||
4. Monitorar o progresso à medida que a execução avança pelo pipeline
|
||||
|
||||
### Monitoramento e Análises
|
||||
|
||||
A plataforma Enterprise oferece recursos abrangentes de observabilidade:
|
||||
|
||||
- **Gestão das Execuções**: Acompanhe execuções ativas e concluídas
|
||||
- **Traces**: Quebra detalhada de cada execução
|
||||
- **Métricas**: Uso de tokens, tempos de execução e custos
|
||||
- **Visualização em Linha do Tempo**: Representação visual das sequências de tarefas
|
||||
|
||||
### Funcionalidades Avançadas
|
||||
|
||||
A plataforma Enterprise também oferece:
|
||||
|
||||
- **Gerenciamento de Variáveis de Ambiente**: Armazene e gerencie com segurança as chaves de API
|
||||
- **Conexões com LLM**: Configure integrações com diversos provedores de LLM
|
||||
- **Repositório Custom Tools**: Crie, compartilhe e instale ferramentas
|
||||
- **Crew Studio**: Monte crews via interface de chat sem escrever código
|
||||
|
||||
## Solução de Problemas em Falhas de Implantação
|
||||
|
||||
Se sua implantação falhar, verifique estes problemas comuns:
|
||||
|
||||
### Falhas de Build
|
||||
|
||||
#### Arquivo uv.lock Ausente
|
||||
|
||||
**Sintoma**: Build falha no início com erros de resolução de dependências
|
||||
|
||||
**Solução**: Gere e faça commit do arquivo lock:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
<Warning>
|
||||
O arquivo `uv.lock` é obrigatório para todas as implantações. Sem ele, a plataforma
|
||||
não consegue instalar suas dependências de forma confiável.
|
||||
</Warning>
|
||||
|
||||
#### Estrutura de Projeto Incorreta
|
||||
|
||||
**Sintoma**: Erros "Could not find entry point" ou "Module not found"
|
||||
|
||||
**Solução**: Verifique se seu projeto corresponde à estrutura esperada:
|
||||
|
||||
- **Tanto Crews quanto Flows**: Devem ter ponto de entrada em `src/project_name/main.py`
|
||||
- **Crews**: Usam uma função `run()` como ponto de entrada
|
||||
- **Flows**: Usam uma função `kickoff()` como ponto de entrada
|
||||
|
||||
Veja [Preparar para Implantação](/pt-BR/enterprise/guides/prepare-for-deployment) para diagramas de estrutura detalhados.
|
||||
|
||||
#### Decorador CrewBase Ausente
|
||||
|
||||
**Sintoma**: Erros "Crew not found", "Config not found" ou erros de configuração de agent/task
|
||||
|
||||
**Solução**: Certifique-se de que **todas** as classes crew usam o decorador `@CrewBase`:
|
||||
|
||||
```python
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
|
||||
@CrewBase # Este decorador é OBRIGATÓRIO
|
||||
class YourCrew():
|
||||
"""Descrição do seu crew"""
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# ... resto da definição do crew
|
||||
```
|
||||
|
||||
<Info>
|
||||
Isso se aplica a Crews independentes E crews embutidos dentro de projetos Flow.
|
||||
Toda classe crew precisa do decorador.
|
||||
</Info>
|
||||
|
||||
#### Tipo Incorreto no pyproject.toml
|
||||
|
||||
**Sintoma**: Build tem sucesso mas falha em runtime, ou comportamento inesperado
|
||||
|
||||
**Solução**: Verifique se a seção `[tool.crewai]` corresponde ao tipo do seu projeto:
|
||||
|
||||
```toml
|
||||
# Para projetos Crew:
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
|
||||
# Para projetos Flow:
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
|
||||
### Falhas de Runtime
|
||||
|
||||
#### Falhas de Conexão com LLM
|
||||
|
||||
**Sintoma**: Erros de chave API, "model not found" ou falhas de autenticação
|
||||
|
||||
**Solução**:
|
||||
1. Verifique se a chave API do seu provedor LLM está corretamente definida nas variáveis de ambiente
|
||||
2. Certifique-se de que os nomes das variáveis de ambiente correspondem ao que seu código espera
|
||||
3. Teste localmente com exatamente as mesmas variáveis de ambiente antes de implantar
|
||||
|
||||
#### Erros de Execução do Crew
|
||||
|
||||
**Sintoma**: Crew inicia mas falha durante a execução
|
||||
|
||||
**Solução**:
|
||||
1. Verifique os logs de execução no dashboard AMP (aba Traces)
|
||||
2. Verifique se todas as ferramentas têm as chaves API necessárias configuradas
|
||||
3. Certifique-se de que as configurações de agents em `agents.yaml` são válidas
|
||||
4. Verifique se há erros de sintaxe nas configurações de tasks em `tasks.yaml`
|
||||
|
||||
<Card title="Precisa de Ajuda?" icon="headset" href="mailto:support@crewai.com">
|
||||
Entre em contato com nossa equipe de suporte para ajuda com questões de
|
||||
implantação ou dúvidas sobre a plataforma AMP.
|
||||
</Card>
|
||||
@@ -5,9 +5,54 @@ icon: "user-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
Human-In-The-Loop (HITL) é uma abordagem poderosa que combina inteligência artificial com expertise humana para aprimorar a tomada de decisão e melhorar os resultados das tarefas. Este guia mostra como implementar HITL dentro do CrewAI.
|
||||
Human-In-The-Loop (HITL) é uma abordagem poderosa que combina inteligência artificial com expertise humana para aprimorar a tomada de decisão e melhorar os resultados das tarefas. Este guia mostra como implementar HITL dentro do CrewAI Enterprise.
|
||||
|
||||
## Configurando Workflows HITL
|
||||
## Abordagens HITL no CrewAI
|
||||
|
||||
CrewAI oferece duas abordagens para implementar workflows human-in-the-loop:
|
||||
|
||||
| Abordagem | Melhor Para | Versão |
|
||||
|----------|----------|---------|
|
||||
| **Baseada em Flow** (decorador `@human_feedback`) | Produção com UI Enterprise, workflows email-first, recursos completos da plataforma | **1.8.0+** |
|
||||
| **Baseada em Webhook** | Integrações customizadas, sistemas externos (Slack, Teams, etc.), configurações legadas | Todas as versões |
|
||||
|
||||
## HITL Baseado em Flow com Plataforma Enterprise
|
||||
|
||||
<Note>
|
||||
O decorador `@human_feedback` requer **CrewAI versão 1.8.0 ou superior**.
|
||||
</Note>
|
||||
|
||||
Ao usar o decorador `@human_feedback` em seus Flows, o CrewAI Enterprise oferece um **sistema HITL email-first** que permite que qualquer pessoa com um endereço de email responda a solicitações de revisão:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Design Email-First" icon="envelope">
|
||||
Respondentes recebem notificações por email e podem responder diretamente—nenhum login necessário.
|
||||
</Card>
|
||||
<Card title="Revisão no Dashboard" icon="desktop">
|
||||
Revise e responda a solicitações HITL no dashboard Enterprise quando preferir.
|
||||
</Card>
|
||||
<Card title="Roteamento Flexível" icon="route">
|
||||
Direcione solicitações para emails específicos com base em padrões de método ou obtenha do estado do flow.
|
||||
</Card>
|
||||
<Card title="Resposta Automática" icon="clock">
|
||||
Configure respostas automáticas de fallback quando nenhum humano responder dentro do timeout.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Principais Benefícios
|
||||
|
||||
- **Respondentes externos**: Qualquer pessoa com email pode responder, mesmo não sendo usuário da plataforma
|
||||
- **Atribuição dinâmica**: Obtenha o email do responsável do estado do flow (ex: `account_owner_email`)
|
||||
- **Configuração simples**: Roteamento baseado em email é mais fácil de configurar do que gerenciamento de usuários/funções
|
||||
- **Fallback do criador do deployment**: Se nenhuma regra de roteamento corresponder, o criador do deployment é notificado
|
||||
|
||||
<Tip>
|
||||
Para detalhes de implementação do decorador `@human_feedback`, consulte o guia [Feedback Humano em Flows](/pt-BR/learn/human-feedback-in-flows).
|
||||
</Tip>
|
||||
|
||||
## Configurando Workflows HITL Baseados em Webhook
|
||||
|
||||
Para integrações customizadas com sistemas externos como Slack, Microsoft Teams ou suas próprias aplicações, você pode usar a abordagem baseada em webhook:
|
||||
|
||||
<Steps>
|
||||
<Step title="Configure Sua Tarefa">
|
||||
@@ -99,3 +144,14 @@ Workflows HITL são particularmente valiosos para:
|
||||
- Operações sensíveis ou de alto risco
|
||||
- Tarefas criativas que exigem julgamento humano
|
||||
- Revisões de conformidade e regulatórias
|
||||
|
||||
## Saiba Mais
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Gerenciamento HITL para Flows" icon="users-gear" href="/pt-BR/enterprise/features/flow-hitl-management">
|
||||
Explore os recursos completos da plataforma HITL para Flows, incluindo notificações por email, regras de roteamento, resposta automática e análises.
|
||||
</Card>
|
||||
<Card title="Feedback Humano em Flows" icon="code" href="/pt-BR/learn/human-feedback-in-flows">
|
||||
Guia de implementação para o decorador `@human_feedback` em seus Flows.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
305
docs/pt-BR/enterprise/guides/prepare-for-deployment.mdx
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
title: "Preparar para Implantação"
|
||||
description: "Certifique-se de que seu Crew ou Flow está pronto para implantação no CrewAI AMP"
|
||||
icon: "clipboard-check"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Antes de implantar no CrewAI AMP, é crucial verificar se seu projeto está estruturado corretamente.
|
||||
Tanto Crews quanto Flows podem ser implantados como "automações", mas eles têm estruturas de projeto
|
||||
e requisitos diferentes que devem ser atendidos para uma implantação bem-sucedida.
|
||||
</Note>
|
||||
|
||||
## Entendendo Automações
|
||||
|
||||
No CrewAI AMP, **automações** é o termo geral para projetos de IA Agêntica implantáveis. Uma automação pode ser:
|
||||
|
||||
- **Um Crew**: Uma equipe independente de agentes de IA trabalhando juntos em tarefas
|
||||
- **Um Flow**: Um workflow orquestrado que pode combinar múltiplos crews, chamadas diretas de LLM e lógica procedural
|
||||
|
||||
Entender qual tipo você está implantando é essencial porque eles têm estruturas de projeto e pontos de entrada diferentes.
|
||||
|
||||
## Crews vs Flows: Principais Diferenças
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Projetos Crew" icon="users">
|
||||
Equipes de agentes de IA independentes com `crew.py` definindo agentes e tarefas. Ideal para tarefas focadas e colaborativas.
|
||||
</Card>
|
||||
<Card title="Projetos Flow" icon="diagram-project">
|
||||
Workflows orquestrados com crews embutidos em uma pasta `crews/`. Ideal para processos complexos de múltiplas etapas.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| Aspecto | Crew | Flow |
|
||||
|---------|------|------|
|
||||
| **Estrutura do projeto** | `src/project_name/` com `crew.py` | `src/project_name/` com pasta `crews/` |
|
||||
| **Localização da lógica principal** | `src/project_name/crew.py` | `src/project_name/main.py` (classe Flow) |
|
||||
| **Função de ponto de entrada** | `run()` em `main.py` | `kickoff()` em `main.py` |
|
||||
| **Tipo no pyproject.toml** | `type = "crew"` | `type = "flow"` |
|
||||
| **Comando CLI de criação** | `crewai create crew name` | `crewai create flow name` |
|
||||
| **Localização da configuração** | `src/project_name/config/` | `src/project_name/crews/crew_name/config/` |
|
||||
| **Pode conter outros crews** | Não | Sim (na pasta `crews/`) |
|
||||
|
||||
## Referência de Estrutura de Projeto
|
||||
|
||||
### Estrutura de Projeto Crew
|
||||
|
||||
Quando você executa `crewai create crew my_crew`, você obtém esta estrutura:
|
||||
|
||||
```
|
||||
my_crew/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # Deve ter type = "crew"
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # OBRIGATÓRIO para implantação
|
||||
└── src/
|
||||
└── my_crew/
|
||||
├── __init__.py
|
||||
├── main.py # Ponto de entrada com função run()
|
||||
├── crew.py # Classe Crew com decorador @CrewBase
|
||||
├── tools/
|
||||
│ ├── custom_tool.py
|
||||
│ └── __init__.py
|
||||
└── config/
|
||||
├── agents.yaml # Definições de agentes
|
||||
└── tasks.yaml # Definições de tarefas
|
||||
```
|
||||
|
||||
<Warning>
|
||||
A estrutura aninhada `src/project_name/` é crítica para Crews.
|
||||
Colocar arquivos no nível errado causará falhas na implantação.
|
||||
</Warning>
|
||||
|
||||
### Estrutura de Projeto Flow
|
||||
|
||||
Quando você executa `crewai create flow my_flow`, você obtém esta estrutura:
|
||||
|
||||
```
|
||||
my_flow/
|
||||
├── .gitignore
|
||||
├── pyproject.toml # Deve ter type = "flow"
|
||||
├── README.md
|
||||
├── .env
|
||||
├── uv.lock # OBRIGATÓRIO para implantação
|
||||
└── src/
|
||||
└── my_flow/
|
||||
├── __init__.py
|
||||
├── main.py # Ponto de entrada com função kickoff() + classe Flow
|
||||
├── crews/ # Pasta de crews embutidos
|
||||
│ └── poem_crew/
|
||||
│ ├── __init__.py
|
||||
│ ├── poem_crew.py # Crew com decorador @CrewBase
|
||||
│ └── config/
|
||||
│ ├── agents.yaml
|
||||
│ └── tasks.yaml
|
||||
└── tools/
|
||||
├── __init__.py
|
||||
└── custom_tool.py
|
||||
```
|
||||
|
||||
<Info>
|
||||
Tanto Crews quanto Flows usam a estrutura `src/project_name/`.
|
||||
A diferença chave é que Flows têm uma pasta `crews/` para crews embutidos,
|
||||
enquanto Crews têm `crew.py` diretamente na pasta do projeto.
|
||||
</Info>
|
||||
|
||||
## Checklist Pré-Implantação
|
||||
|
||||
Use este checklist para verificar se seu projeto está pronto para implantação.
|
||||
|
||||
### 1. Verificar Configuração do pyproject.toml
|
||||
|
||||
Seu `pyproject.toml` deve incluir a seção `[tool.crewai]` correta:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Para Crews">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "crew"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Para Flows">
|
||||
```toml
|
||||
[tool.crewai]
|
||||
type = "flow"
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
Se o `type` não corresponder à estrutura do seu projeto, o build falhará ou
|
||||
a automação não funcionará corretamente.
|
||||
</Warning>
|
||||
|
||||
### 2. Garantir que o Arquivo uv.lock Existe
|
||||
|
||||
CrewAI usa `uv` para gerenciamento de dependências. O arquivo `uv.lock` garante builds reproduzíveis e é **obrigatório** para implantação.
|
||||
|
||||
```bash
|
||||
# Gerar ou atualizar o arquivo lock
|
||||
uv lock
|
||||
|
||||
# Verificar se existe
|
||||
ls -la uv.lock
|
||||
```
|
||||
|
||||
Se o arquivo não existir, execute `uv lock` e faça commit no seu repositório:
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
git add uv.lock
|
||||
git commit -m "Add uv.lock for deployment"
|
||||
git push
|
||||
```
|
||||
|
||||
### 3. Validar Uso do Decorador CrewBase
|
||||
|
||||
**Toda classe crew deve usar o decorador `@CrewBase`.** Isso se aplica a:
|
||||
|
||||
- Projetos crew independentes
|
||||
- Crews embutidos dentro de projetos Flow
|
||||
|
||||
```python
|
||||
from crewai import Agent, Crew, Process, Task
|
||||
from crewai.project import CrewBase, agent, crew, task
|
||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||
from typing import List
|
||||
|
||||
@CrewBase # Este decorador é OBRIGATÓRIO
|
||||
class MyCrew():
|
||||
"""Descrição do meu crew"""
|
||||
|
||||
agents: List[BaseAgent]
|
||||
tasks: List[Task]
|
||||
|
||||
@agent
|
||||
def my_agent(self) -> Agent:
|
||||
return Agent(
|
||||
config=self.agents_config['my_agent'], # type: ignore[index]
|
||||
verbose=True
|
||||
)
|
||||
|
||||
@task
|
||||
def my_task(self) -> Task:
|
||||
return Task(
|
||||
config=self.tasks_config['my_task'] # type: ignore[index]
|
||||
)
|
||||
|
||||
@crew
|
||||
def crew(self) -> Crew:
|
||||
return Crew(
|
||||
agents=self.agents,
|
||||
tasks=self.tasks,
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
)
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Se você esquecer o decorador `@CrewBase`, sua implantação falhará com
|
||||
erros sobre configurações de agents ou tasks ausentes.
|
||||
</Warning>
|
||||
|
||||
### 4. Verificar Pontos de Entrada do Projeto
|
||||
|
||||
Tanto Crews quanto Flows têm seu ponto de entrada em `src/project_name/main.py`:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Para Crews">
|
||||
O ponto de entrada usa uma função `run()`:
|
||||
|
||||
```python
|
||||
# src/my_crew/main.py
|
||||
from my_crew.crew import MyCrew
|
||||
|
||||
def run():
|
||||
"""Executa o crew."""
|
||||
inputs = {'topic': 'AI in Healthcare'}
|
||||
result = MyCrew().crew().kickoff(inputs=inputs)
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Para Flows">
|
||||
O ponto de entrada usa uma função `kickoff()` com uma classe Flow:
|
||||
|
||||
```python
|
||||
# src/my_flow/main.py
|
||||
from crewai.flow import Flow, listen, start
|
||||
from my_flow.crews.poem_crew.poem_crew import PoemCrew
|
||||
|
||||
class MyFlow(Flow):
|
||||
@start()
|
||||
def begin(self):
|
||||
# Lógica do Flow aqui
|
||||
result = PoemCrew().crew().kickoff(inputs={...})
|
||||
return result
|
||||
|
||||
def kickoff():
|
||||
"""Executa o flow."""
|
||||
MyFlow().kickoff()
|
||||
|
||||
if __name__ == "__main__":
|
||||
kickoff()
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 5. Preparar Variáveis de Ambiente
|
||||
|
||||
Antes da implantação, certifique-se de ter:
|
||||
|
||||
1. **Chaves de API de LLM** prontas (OpenAI, Anthropic, Google, etc.)
|
||||
2. **Chaves de API de ferramentas** se estiver usando ferramentas externas (Serper, etc.)
|
||||
|
||||
<Tip>
|
||||
Teste seu projeto localmente com as mesmas variáveis de ambiente antes de implantar
|
||||
para detectar problemas de configuração antecipadamente.
|
||||
</Tip>
|
||||
|
||||
## Comandos de Validação Rápida
|
||||
|
||||
Execute estes comandos a partir da raiz do seu projeto para verificar rapidamente sua configuração:
|
||||
|
||||
```bash
|
||||
# 1. Verificar tipo do projeto no pyproject.toml
|
||||
grep -A2 "\[tool.crewai\]" pyproject.toml
|
||||
|
||||
# 2. Verificar se uv.lock existe
|
||||
ls -la uv.lock || echo "ERRO: uv.lock ausente! Execute 'uv lock'"
|
||||
|
||||
# 3. Verificar se estrutura src/ existe
|
||||
ls -la src/*/main.py 2>/dev/null || echo "Nenhum main.py encontrado em src/"
|
||||
|
||||
# 4. Para Crews - verificar se crew.py existe
|
||||
ls -la src/*/crew.py 2>/dev/null || echo "Nenhum crew.py (esperado para Crews)"
|
||||
|
||||
# 5. Para Flows - verificar se pasta crews/ existe
|
||||
ls -la src/*/crews/ 2>/dev/null || echo "Nenhuma pasta crews/ (esperado para Flows)"
|
||||
|
||||
# 6. Verificar uso do CrewBase
|
||||
grep -r "@CrewBase" . --include="*.py"
|
||||
```
|
||||
|
||||
## Erros Comuns de Configuração
|
||||
|
||||
| Erro | Sintoma | Correção |
|
||||
|------|---------|----------|
|
||||
| `uv.lock` ausente | Build falha durante resolução de dependências | Execute `uv lock` e faça commit |
|
||||
| `type` errado no pyproject.toml | Build bem-sucedido mas falha em runtime | Altere para o tipo correto |
|
||||
| Decorador `@CrewBase` ausente | Erros "Config not found" | Adicione decorador a todas as classes crew |
|
||||
| Arquivos na raiz ao invés de `src/` | Ponto de entrada não encontrado | Mova para `src/project_name/` |
|
||||
| `run()` ou `kickoff()` ausente | Não é possível iniciar automação | Adicione a função de entrada correta |
|
||||
|
||||
## Próximos Passos
|
||||
|
||||
Uma vez que seu projeto passar por todos os itens do checklist, você está pronto para implantar:
|
||||
|
||||
<Card title="Deploy para AMP" icon="rocket" href="/pt-BR/enterprise/guides/deploy-to-amp">
|
||||
Siga o guia de implantação para implantar seu Crew ou Flow no CrewAI AMP usando
|
||||
a CLI, interface web ou integração CI/CD.
|
||||
</Card>
|
||||
@@ -200,6 +200,25 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `clientData` (array, opcional): Dados específicos do cliente. Cada item é um objeto com `key` (string) e `value` (string).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/update_contact_group">
|
||||
**Descrição:** Atualizar informações de um grupo de contatos.
|
||||
|
||||
**Parâmetros:**
|
||||
- `resourceName` (string, obrigatório): O nome do recurso do grupo de contatos (ex: 'contactGroups/myContactGroup').
|
||||
- `name` (string, obrigatório): O nome do grupo de contatos.
|
||||
- `clientData` (array, opcional): Dados específicos do cliente. Cada item é um objeto com `key` (string) e `value` (string).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_contacts/delete_contact_group">
|
||||
**Descrição:** Excluir um grupo de contatos.
|
||||
|
||||
**Parâmetros:**
|
||||
- `resourceName` (string, obrigatório): O nome do recurso do grupo de contatos a excluir (ex: 'contactGroups/myContactGroup').
|
||||
- `deleteContacts` (boolean, opcional): Se os contatos do grupo também devem ser excluídos. Padrão: false
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -131,6 +131,297 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `endIndex` (integer, obrigatório): O índice final do intervalo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_document_with_content">
|
||||
**Descrição:** Criar um novo documento do Google com conteúdo em uma única ação.
|
||||
|
||||
**Parâmetros:**
|
||||
- `title` (string, obrigatório): O título para o novo documento. Aparece no topo do documento e no Google Drive.
|
||||
- `content` (string, opcional): O conteúdo de texto a inserir no documento. Use `\n` para novos parágrafos.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/append_text">
|
||||
**Descrição:** Adicionar texto ao final de um documento do Google. Insere automaticamente no final do documento sem necessidade de especificar um índice.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento obtido da resposta de create_document ou URL.
|
||||
- `text` (string, obrigatório): Texto a adicionar ao final do documento. Use `\n` para novos parágrafos.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_bold">
|
||||
**Descrição:** Aplicar ou remover formatação de negrito em texto de um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `bold` (boolean, obrigatório): Defina `true` para aplicar negrito, `false` para remover negrito.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_italic">
|
||||
**Descrição:** Aplicar ou remover formatação de itálico em texto de um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `italic` (boolean, obrigatório): Defina `true` para aplicar itálico, `false` para remover itálico.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_underline">
|
||||
**Descrição:** Adicionar ou remover formatação de sublinhado em texto de um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `underline` (boolean, obrigatório): Defina `true` para sublinhar, `false` para remover sublinhado.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_strikethrough">
|
||||
**Descrição:** Adicionar ou remover formatação de tachado em texto de um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `strikethrough` (boolean, obrigatório): Defina `true` para adicionar tachado, `false` para remover.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_font_size">
|
||||
**Descrição:** Alterar o tamanho da fonte do texto em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `fontSize` (number, obrigatório): Tamanho da fonte em pontos. Tamanhos comuns: 10, 11, 12, 14, 16, 18, 24, 36.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_text_color">
|
||||
**Descrição:** Alterar a cor do texto usando valores RGB (escala 0-1) em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a formatar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a formatar (exclusivo).
|
||||
- `red` (number, obrigatório): Componente vermelho (0-1). Exemplo: `1` para vermelho total.
|
||||
- `green` (number, obrigatório): Componente verde (0-1). Exemplo: `0.5` para metade verde.
|
||||
- `blue` (number, obrigatório): Componente azul (0-1). Exemplo: `0` para sem azul.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_hyperlink">
|
||||
**Descrição:** Transformar texto existente em um hyperlink clicável em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do texto a transformar em link.
|
||||
- `endIndex` (integer, obrigatório): Posição final do texto a transformar em link (exclusivo).
|
||||
- `url` (string, obrigatório): A URL para a qual o link deve apontar. Exemplo: `"https://example.com"`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/apply_heading_style">
|
||||
**Descrição:** Aplicar um estilo de título ou parágrafo a um intervalo de texto em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do(s) parágrafo(s) a estilizar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do(s) parágrafo(s) a estilizar.
|
||||
- `style` (string, obrigatório): O estilo a aplicar. Opções: `NORMAL_TEXT`, `TITLE`, `SUBTITLE`, `HEADING_1`, `HEADING_2`, `HEADING_3`, `HEADING_4`, `HEADING_5`, `HEADING_6`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_paragraph_alignment">
|
||||
**Descrição:** Definir o alinhamento de texto para parágrafos em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do(s) parágrafo(s) a alinhar.
|
||||
- `endIndex` (integer, obrigatório): Posição final do(s) parágrafo(s) a alinhar.
|
||||
- `alignment` (string, obrigatório): Alinhamento do texto. Opções: `START` (esquerda), `CENTER`, `END` (direita), `JUSTIFIED`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/set_line_spacing">
|
||||
**Descrição:** Definir o espaçamento entre linhas para parágrafos em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial do(s) parágrafo(s).
|
||||
- `endIndex` (integer, obrigatório): Posição final do(s) parágrafo(s).
|
||||
- `lineSpacing` (number, obrigatório): Espaçamento entre linhas como porcentagem. `100` = simples, `115` = 1.15x, `150` = 1.5x, `200` = duplo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_paragraph_bullets">
|
||||
**Descrição:** Converter parágrafos em uma lista com marcadores ou numerada em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial dos parágrafos a converter em lista.
|
||||
- `endIndex` (integer, obrigatório): Posição final dos parágrafos a converter em lista.
|
||||
- `bulletPreset` (string, obrigatório): Estilo de marcadores/numeração. Opções: `BULLET_DISC_CIRCLE_SQUARE`, `BULLET_DIAMONDX_ARROW3D_SQUARE`, `BULLET_CHECKBOX`, `BULLET_ARROW_DIAMOND_DISC`, `BULLET_STAR_CIRCLE_SQUARE`, `NUMBERED_DECIMAL_ALPHA_ROMAN`, `NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS`, `NUMBERED_DECIMAL_NESTED`, `NUMBERED_UPPERALPHA_ALPHA_ROMAN`, `NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_paragraph_bullets">
|
||||
**Descrição:** Remover marcadores ou numeração de parágrafos em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `startIndex` (integer, obrigatório): Posição inicial dos parágrafos de lista.
|
||||
- `endIndex` (integer, obrigatório): Posição final dos parágrafos de lista.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_with_content">
|
||||
**Descrição:** Inserir uma tabela com conteúdo em um documento do Google em uma única ação. Forneça o conteúdo como um array 2D.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `rows` (integer, obrigatório): Número de linhas na tabela.
|
||||
- `columns` (integer, obrigatório): Número de colunas na tabela.
|
||||
- `index` (integer, opcional): Posição para inserir a tabela. Se não fornecido, a tabela é inserida no final do documento.
|
||||
- `content` (array, obrigatório): Conteúdo da tabela como um array 2D. Cada array interno é uma linha. Exemplo: `[["Ano", "Receita"], ["2023", "$43B"], ["2024", "$45B"]]`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_row">
|
||||
**Descrição:** Inserir uma nova linha acima ou abaixo de uma célula de referência em uma tabela existente.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela. Obtenha de get_document.
|
||||
- `rowIndex` (integer, obrigatório): Índice da linha (baseado em 0) da célula de referência.
|
||||
- `columnIndex` (integer, opcional): Índice da coluna (baseado em 0) da célula de referência. Padrão: `0`.
|
||||
- `insertBelow` (boolean, opcional): Se `true`, insere abaixo da linha de referência. Se `false`, insere acima. Padrão: `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_table_column">
|
||||
**Descrição:** Inserir uma nova coluna à esquerda ou à direita de uma célula de referência em uma tabela existente.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela.
|
||||
- `rowIndex` (integer, opcional): Índice da linha (baseado em 0) da célula de referência. Padrão: `0`.
|
||||
- `columnIndex` (integer, obrigatório): Índice da coluna (baseado em 0) da célula de referência.
|
||||
- `insertRight` (boolean, opcional): Se `true`, insere à direita. Se `false`, insere à esquerda. Padrão: `true`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_row">
|
||||
**Descrição:** Excluir uma linha de uma tabela existente em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela.
|
||||
- `rowIndex` (integer, obrigatório): Índice da linha (baseado em 0) a excluir.
|
||||
- `columnIndex` (integer, opcional): Índice da coluna (baseado em 0) de qualquer célula na linha. Padrão: `0`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_table_column">
|
||||
**Descrição:** Excluir uma coluna de uma tabela existente em um documento do Google.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela.
|
||||
- `rowIndex` (integer, opcional): Índice da linha (baseado em 0) de qualquer célula na coluna. Padrão: `0`.
|
||||
- `columnIndex` (integer, obrigatório): Índice da coluna (baseado em 0) a excluir.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/merge_table_cells">
|
||||
**Descrição:** Mesclar um intervalo de células de tabela em uma única célula. O conteúdo de todas as células é preservado.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela.
|
||||
- `rowIndex` (integer, obrigatório): Índice da linha inicial (baseado em 0) para a mesclagem.
|
||||
- `columnIndex` (integer, obrigatório): Índice da coluna inicial (baseado em 0) para a mesclagem.
|
||||
- `rowSpan` (integer, obrigatório): Número de linhas a mesclar.
|
||||
- `columnSpan` (integer, obrigatório): Número de colunas a mesclar.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/unmerge_table_cells">
|
||||
**Descrição:** Desfazer a mesclagem de células de tabela previamente mescladas, retornando-as a células individuais.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `tableStartIndex` (integer, obrigatório): O índice inicial da tabela.
|
||||
- `rowIndex` (integer, obrigatório): Índice da linha (baseado em 0) da célula mesclada.
|
||||
- `columnIndex` (integer, obrigatório): Índice da coluna (baseado em 0) da célula mesclada.
|
||||
- `rowSpan` (integer, obrigatório): Número de linhas que a célula mesclada abrange.
|
||||
- `columnSpan` (integer, obrigatório): Número de colunas que a célula mesclada abrange.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_inline_image">
|
||||
**Descrição:** Inserir uma imagem de uma URL pública em um documento do Google. A imagem deve ser publicamente acessível, ter menos de 50MB e estar no formato PNG/JPEG/GIF.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `uri` (string, obrigatório): URL pública da imagem. Deve ser acessível sem autenticação.
|
||||
- `index` (integer, opcional): Posição para inserir a imagem. Se não fornecido, a imagem é inserida no final do documento. Padrão: `1`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/insert_section_break">
|
||||
**Descrição:** Inserir uma quebra de seção para criar seções de documento com formatação diferente.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `index` (integer, obrigatório): Posição para inserir a quebra de seção.
|
||||
- `sectionType` (string, obrigatório): O tipo de quebra de seção. Opções: `CONTINUOUS` (permanece na mesma página), `NEXT_PAGE` (inicia uma nova página).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_header">
|
||||
**Descrição:** Criar um cabeçalho para o documento. Retorna um headerId que pode ser usado com insert_text para adicionar conteúdo ao cabeçalho.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `type` (string, opcional): Tipo de cabeçalho. Opções: `DEFAULT`. Padrão: `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/create_footer">
|
||||
**Descrição:** Criar um rodapé para o documento. Retorna um footerId que pode ser usado com insert_text para adicionar conteúdo ao rodapé.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `type` (string, opcional): Tipo de rodapé. Opções: `DEFAULT`. Padrão: `DEFAULT`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_header">
|
||||
**Descrição:** Excluir um cabeçalho do documento. Use get_document para encontrar o headerId.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `headerId` (string, obrigatório): O ID do cabeçalho a excluir. Obtenha da resposta de get_document.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_docs/delete_footer">
|
||||
**Descrição:** Excluir um rodapé do documento. Use get_document para encontrar o footerId.
|
||||
|
||||
**Parâmetros:**
|
||||
- `documentId` (string, obrigatório): O ID do documento.
|
||||
- `footerId` (string, obrigatório): O ID do rodapé a excluir. Obtenha da resposta de get_document.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -61,6 +61,22 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_metadata">
|
||||
**Descrição:** Obter metadados leves de uma apresentação (título, número de slides, IDs dos slides). Use isso primeiro antes de recuperar o conteúdo completo.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação a ser recuperada.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation_text">
|
||||
**Descrição:** Extrair todo o conteúdo de texto de uma apresentação. Retorna IDs dos slides e texto de formas e tabelas apenas (sem formatação).
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_presentation">
|
||||
**Descrição:** Recupera uma apresentação por ID.
|
||||
|
||||
@@ -80,6 +96,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_slide_text">
|
||||
**Descrição:** Extrair conteúdo de texto de um único slide. Retorna apenas texto de formas e tabelas (sem formatação ou estilo).
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `pageObjectId` (string, obrigatório): O ID do slide/página para obter o texto.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/get_page">
|
||||
**Descrição:** Recupera uma página específica por seu ID.
|
||||
|
||||
@@ -98,6 +123,120 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide">
|
||||
**Descrição:** Adicionar um slide em branco adicional a uma apresentação. Novas apresentações já possuem um slide em branco - verifique get_presentation_metadata primeiro. Para slides com áreas de título/corpo, use create_slide_with_layout.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `insertionIndex` (integer, opcional): Onde inserir o slide (baseado em 0). Se omitido, adiciona no final.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_slide_with_layout">
|
||||
**Descrição:** Criar um slide com layout predefinido contendo áreas de espaço reservado para título, corpo, etc. Melhor que create_slide para conteúdo estruturado. Após criar, use get_page para encontrar os IDs de espaço reservado, depois insira texto neles.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `layout` (string, obrigatório): Tipo de layout. Um de: `BLANK`, `TITLE`, `TITLE_AND_BODY`, `TITLE_AND_TWO_COLUMNS`, `TITLE_ONLY`, `SECTION_HEADER`, `ONE_COLUMN_TEXT`, `MAIN_POINT`, `BIG_NUMBER`. TITLE_AND_BODY é melhor para título+descrição. TITLE para slides apenas com título. SECTION_HEADER para divisores de seção.
|
||||
- `insertionIndex` (integer, opcional): Onde inserir (baseado em 0). Se omitido, adiciona no final.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_text_box">
|
||||
**Descrição:** Criar uma caixa de texto em um slide com conteúdo. Use para títulos, descrições, parágrafos - não para tabelas. Opcionalmente especifique posição (x, y) e tamanho (width, height) em unidades EMU (914400 EMU = 1 polegada).
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para adicionar a caixa de texto.
|
||||
- `text` (string, obrigatório): O conteúdo de texto da caixa de texto.
|
||||
- `x` (integer, opcional): Posição X em EMU (914400 = 1 polegada). Padrão: 914400 (1 polegada da esquerda).
|
||||
- `y` (integer, opcional): Posição Y em EMU (914400 = 1 polegada). Padrão: 914400 (1 polegada do topo).
|
||||
- `width` (integer, opcional): Largura em EMU. Padrão: 7315200 (~8 polegadas).
|
||||
- `height` (integer, opcional): Altura em EMU. Padrão: 914400 (~1 polegada).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/delete_slide">
|
||||
**Descrição:** Remover um slide de uma apresentação. Use get_presentation primeiro para encontrar o ID do slide.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do objeto do slide a excluir. Obtenha de get_presentation.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/duplicate_slide">
|
||||
**Descrição:** Criar uma cópia de um slide existente. A duplicata é inserida imediatamente após o original.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do objeto do slide a duplicar. Obtenha de get_presentation.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/move_slides">
|
||||
**Descrição:** Reordenar slides movendo-os para uma nova posição. Os IDs dos slides devem estar na ordem atual da apresentação (sem duplicatas).
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideIds` (array de strings, obrigatório): Array de IDs dos slides a mover. Obrigatoriamente na ordem atual da apresentação.
|
||||
- `insertionIndex` (integer, obrigatório): Posição de destino (baseado em 0). 0 = início, número de slides = final.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_youtube_video">
|
||||
**Descrição:** Incorporar um vídeo do YouTube em um slide. O ID do vídeo é o valor após "v=" nas URLs do YouTube (ex: para youtube.com/watch?v=abc123, use "abc123").
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para adicionar o vídeo. Obtenha de get_presentation.
|
||||
- `videoId` (string, obrigatório): O ID do vídeo do YouTube (o valor após v= na URL).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/insert_drive_video">
|
||||
**Descrição:** Incorporar um vídeo do Google Drive em um slide. O ID do arquivo pode ser encontrado na URL do arquivo no Drive.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para adicionar o vídeo. Obtenha de get_presentation.
|
||||
- `fileId` (string, obrigatório): O ID do arquivo do Google Drive do vídeo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/set_slide_background_image">
|
||||
**Descrição:** Definir uma imagem de fundo para um slide. A URL da imagem deve ser publicamente acessível.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para definir o fundo. Obtenha de get_presentation.
|
||||
- `imageUrl` (string, obrigatório): URL publicamente acessível da imagem a usar como fundo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table">
|
||||
**Descrição:** Criar uma tabela vazia em um slide. Para criar uma tabela com conteúdo, use create_table_with_content.
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para adicionar a tabela. Obtenha de get_presentation.
|
||||
- `rows` (integer, obrigatório): Número de linhas na tabela.
|
||||
- `columns` (integer, obrigatório): Número de colunas na tabela.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/create_table_with_content">
|
||||
**Descrição:** Criar uma tabela com conteúdo em uma única ação. Forneça o conteúdo como uma matriz 2D onde cada array interno é uma linha. Exemplo: [["Cabeçalho1", "Cabeçalho2"], ["Linha1Col1", "Linha1Col2"]].
|
||||
|
||||
**Parâmetros:**
|
||||
- `presentationId` (string, obrigatório): O ID da apresentação.
|
||||
- `slideId` (string, obrigatório): O ID do slide para adicionar a tabela. Obtenha de get_presentation.
|
||||
- `rows` (integer, obrigatório): Número de linhas na tabela.
|
||||
- `columns` (integer, obrigatório): Número de colunas na tabela.
|
||||
- `content` (array, obrigatório): Conteúdo da tabela como matriz 2D. Cada array interno é uma linha. Exemplo: [["Ano", "Receita"], ["2023", "$10M"]].
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="google_slides/import_data_from_sheet">
|
||||
**Descrição:** Importa dados de uma planilha do Google para uma apresentação.
|
||||
|
||||
|
||||
@@ -148,6 +148,16 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_table_data">
|
||||
**Descrição:** Obter dados de uma tabela específica em uma planilha do Excel.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_id` (string, obrigatório): O ID do arquivo Excel.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha.
|
||||
- `table_name` (string, obrigatório): Nome da tabela.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/create_chart">
|
||||
**Descrição:** Criar um gráfico em uma planilha do Excel.
|
||||
|
||||
@@ -180,6 +190,15 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/get_used_range_metadata">
|
||||
**Descrição:** Obter os metadados do intervalo usado (apenas dimensões, sem dados) de uma planilha do Excel.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_id` (string, obrigatório): O ID do arquivo Excel.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_excel/list_charts">
|
||||
**Descrição:** Obter todos os gráficos em uma planilha do Excel.
|
||||
|
||||
|
||||
@@ -150,6 +150,49 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `item_id` (string, obrigatório): O ID do arquivo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/list_files_by_path">
|
||||
**Descrição:** Listar arquivos e pastas em um caminho específico do OneDrive.
|
||||
|
||||
**Parâmetros:**
|
||||
- `folder_path` (string, obrigatório): O caminho da pasta (ex: 'Documents/Reports').
|
||||
- `top` (integer, opcional): Número de itens a recuperar (máx 1000). Padrão: 50.
|
||||
- `orderby` (string, opcional): Ordenar por campo (ex: "name asc", "lastModifiedDateTime desc"). Padrão: "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_recent_files">
|
||||
**Descrição:** Obter arquivos acessados recentemente no OneDrive.
|
||||
|
||||
**Parâmetros:**
|
||||
- `top` (integer, opcional): Número de itens a recuperar (máx 200). Padrão: 25.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_shared_with_me">
|
||||
**Descrição:** Obter arquivos e pastas compartilhados com o usuário.
|
||||
|
||||
**Parâmetros:**
|
||||
- `top` (integer, opcional): Número de itens a recuperar (máx 200). Padrão: 50.
|
||||
- `orderby` (string, opcional): Ordenar por campo. Padrão: "name asc".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/get_file_by_path">
|
||||
**Descrição:** Obter informações sobre um arquivo ou pasta específica pelo caminho.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_path` (string, obrigatório): O caminho do arquivo ou pasta (ex: 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_onedrive/download_file_by_path">
|
||||
**Descrição:** Baixar um arquivo do OneDrive pelo seu caminho.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_path` (string, obrigatório): O caminho do arquivo (ex: 'Documents/report.docx').
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -132,6 +132,74 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `companyName` (string, opcional): Nome da empresa do contato.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/get_message">
|
||||
**Descrição:** Obter uma mensagem de email específica por ID.
|
||||
|
||||
**Parâmetros:**
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem. Obter pela ação get_messages.
|
||||
- `select` (string, opcional): Lista separada por vírgulas de propriedades a retornar. Exemplo: "id,subject,body,from,receivedDateTime". Padrão: "id,subject,body,from,toRecipients,receivedDateTime".
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/reply_to_email">
|
||||
**Descrição:** Responder a uma mensagem de email.
|
||||
|
||||
**Parâmetros:**
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem a responder. Obter pela ação get_messages.
|
||||
- `comment` (string, obrigatório): O conteúdo da mensagem de resposta. Pode ser texto simples ou HTML. A mensagem original será citada abaixo deste conteúdo.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/forward_email">
|
||||
**Descrição:** Encaminhar uma mensagem de email.
|
||||
|
||||
**Parâmetros:**
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem a encaminhar. Obter pela ação get_messages.
|
||||
- `to_recipients` (array, obrigatório): Array de endereços de email dos destinatários. Exemplo: ["john@example.com", "jane@example.com"].
|
||||
- `comment` (string, opcional): Mensagem opcional a incluir acima do conteúdo encaminhado. Pode ser texto simples ou HTML.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/mark_message_read">
|
||||
**Descrição:** Marcar uma mensagem como lida ou não lida.
|
||||
|
||||
**Parâmetros:**
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem. Obter pela ação get_messages.
|
||||
- `is_read` (boolean, obrigatório): Definir como true para marcar como lida, false para marcar como não lida.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_message">
|
||||
**Descrição:** Excluir uma mensagem de email.
|
||||
|
||||
**Parâmetros:**
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem a excluir. Obter pela ação get_messages.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/update_event">
|
||||
**Descrição:** Atualizar um evento de calendário existente.
|
||||
|
||||
**Parâmetros:**
|
||||
- `event_id` (string, obrigatório): O identificador único do evento. Obter pela ação get_calendar_events.
|
||||
- `subject` (string, opcional): Novo assunto/título do evento.
|
||||
- `start_time` (string, opcional): Nova hora de início no formato ISO 8601 (ex: "2024-01-20T10:00:00"). OBRIGATÓRIO: Também deve fornecer start_timezone ao usar este campo.
|
||||
- `start_timezone` (string, opcional): Fuso horário da hora de início. OBRIGATÓRIO ao atualizar start_time. Exemplos: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `end_time` (string, opcional): Nova hora de término no formato ISO 8601. OBRIGATÓRIO: Também deve fornecer end_timezone ao usar este campo.
|
||||
- `end_timezone` (string, opcional): Fuso horário da hora de término. OBRIGATÓRIO ao atualizar end_time. Exemplos: "Pacific Standard Time", "Eastern Standard Time", "UTC".
|
||||
- `location` (string, opcional): Novo local do evento.
|
||||
- `body` (string, opcional): Novo corpo/descrição do evento. Suporta formatação HTML.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_outlook/delete_event">
|
||||
**Descrição:** Excluir um evento de calendário.
|
||||
|
||||
**Parâmetros:**
|
||||
- `event_id` (string, obrigatório): O identificador único do evento a excluir. Obter pela ação get_calendar_events.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -77,6 +77,17 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drives">
|
||||
**Descrição:** Listar todas as bibliotecas de documentos (drives) em um site do SharePoint. Use isto para descobrir bibliotecas disponíveis antes de usar operações de arquivo.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `top` (integer, opcional): Número máximo de drives a retornar por página (1-999). Padrão: 100
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior para buscar a próxima página de resultados.
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'id,name,webUrl,driveType').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_site_lists">
|
||||
**Descrição:** Obter todas as listas em um site do SharePoint.
|
||||
|
||||
@@ -145,20 +156,317 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_drive_items">
|
||||
**Descrição:** Obter arquivos e pastas de uma biblioteca de documentos do SharePoint.
|
||||
<Accordion title="microsoft_sharepoint/list_files">
|
||||
**Descrição:** Recuperar arquivos e pastas de uma biblioteca de documentos do SharePoint. Por padrão, lista a pasta raiz, mas você pode navegar em subpastas fornecendo um folder_id.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O ID do site do SharePoint.
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `folder_id` (string, opcional): O ID da pasta para listar o conteúdo. Use 'root' para a pasta raiz, ou forneça um ID de pasta de uma chamada anterior de list_files. Padrão: 'root'
|
||||
- `top` (integer, opcional): Número máximo de itens a retornar por página (1-1000). Padrão: 50
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior para buscar a próxima página de resultados.
|
||||
- `orderby` (string, opcional): Ordem de classificação dos resultados (ex: 'name asc', 'size desc', 'lastModifiedDateTime desc'). Padrão: 'name asc'
|
||||
- `filter` (string, opcional): Filtro OData para restringir resultados (ex: 'file ne null' apenas para arquivos, 'folder ne null' apenas para pastas).
|
||||
- `select` (string, opcional): Lista de campos separados por vírgula para retornar (ex: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_drive_item">
|
||||
**Descrição:** Excluir um arquivo ou pasta da biblioteca de documentos do SharePoint.
|
||||
<Accordion title="microsoft_sharepoint/delete_file">
|
||||
**Descrição:** Excluir um arquivo ou pasta de uma biblioteca de documentos do SharePoint. Para pastas, todo o conteúdo é excluído recursivamente. Os itens são movidos para a lixeira do site.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O ID do site do SharePoint.
|
||||
- `item_id` (string, obrigatório): O ID do arquivo ou pasta a excluir.
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo ou pasta a excluir. Obtenha de list_files.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_files_by_path">
|
||||
**Descrição:** Listar arquivos e pastas em uma pasta de biblioteca de documentos do SharePoint pelo caminho. Mais eficiente do que múltiplas chamadas list_files para navegação profunda.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `folder_path` (string, obrigatório): O caminho completo para a pasta sem barras iniciais/finais (ex: 'Documents', 'Reports/2024/Q1').
|
||||
- `top` (integer, opcional): Número máximo de itens a retornar por página (1-1000). Padrão: 50
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior para buscar a próxima página de resultados.
|
||||
- `orderby` (string, opcional): Ordem de classificação dos resultados (ex: 'name asc', 'size desc'). Padrão: 'name asc'
|
||||
- `select` (string, opcional): Lista de campos separados por vírgula para retornar (ex: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/download_file">
|
||||
**Descrição:** Baixar conteúdo bruto de um arquivo de uma biblioteca de documentos do SharePoint. Use apenas para arquivos de texto simples (.txt, .csv, .json). Para arquivos Excel, use as ações específicas de Excel. Para arquivos Word, use get_word_document_content.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo a baixar. Obtenha de list_files ou list_files_by_path.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_file_info">
|
||||
**Descrição:** Recuperar metadados detalhados de um arquivo ou pasta específico em uma biblioteca de documentos do SharePoint, incluindo nome, tamanho, datas de criação/modificação e informações do autor.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo ou pasta. Obtenha de list_files ou list_files_by_path.
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'id,name,size,createdDateTime,lastModifiedDateTime,webUrl,createdBy,lastModifiedBy').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_folder">
|
||||
**Descrição:** Criar uma nova pasta em uma biblioteca de documentos do SharePoint. Por padrão, cria a pasta na raiz; use parent_id para criar subpastas.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `folder_name` (string, obrigatório): Nome para a nova pasta. Não pode conter: \ / : * ? " < > |
|
||||
- `parent_id` (string, opcional): O ID da pasta pai. Use 'root' para a raiz da biblioteca de documentos, ou forneça um ID de pasta de list_files. Padrão: 'root'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/search_files">
|
||||
**Descrição:** Pesquisar arquivos e pastas em uma biblioteca de documentos do SharePoint por palavras-chave. Pesquisa nomes de arquivos, nomes de pastas e conteúdo de arquivos para documentos Office. Não use curingas ou caracteres especiais.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `query` (string, obrigatório): Palavras-chave de pesquisa (ex: 'relatório', 'orçamento 2024'). Curingas como *.txt não são suportados.
|
||||
- `top` (integer, opcional): Número máximo de resultados a retornar por página (1-1000). Padrão: 50
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior para buscar a próxima página de resultados.
|
||||
- `select` (string, opcional): Lista de campos separados por vírgula para retornar (ex: 'id,name,size,folder,file,webUrl,lastModifiedDateTime').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/copy_file">
|
||||
**Descrição:** Copiar um arquivo ou pasta para um novo local dentro do SharePoint. O item original permanece inalterado. A operação de cópia é assíncrona para arquivos grandes.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo ou pasta a copiar. Obtenha de list_files ou search_files.
|
||||
- `destination_folder_id` (string, obrigatório): O ID da pasta de destino. Use 'root' para a pasta raiz, ou um ID de pasta de list_files.
|
||||
- `new_name` (string, opcional): Novo nome para a cópia. Se não fornecido, o nome original é usado.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/move_file">
|
||||
**Descrição:** Mover um arquivo ou pasta para um novo local dentro do SharePoint. O item é removido de sua localização original. Para pastas, todo o conteúdo é movido também.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo ou pasta a mover. Obtenha de list_files ou search_files.
|
||||
- `destination_folder_id` (string, obrigatório): O ID da pasta de destino. Use 'root' para a pasta raiz, ou um ID de pasta de list_files.
|
||||
- `new_name` (string, opcional): Novo nome para o item movido. Se não fornecido, o nome original é mantido.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_worksheets">
|
||||
**Descrição:** Listar todas as planilhas (abas) em uma pasta de trabalho Excel armazenada em uma biblioteca de documentos do SharePoint. Use o nome da planilha retornado com outras ações de Excel.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'id,name,position,visibility').
|
||||
- `filter` (string, opcional): Expressão de filtro OData (ex: "visibility eq 'Visible'" para excluir planilhas ocultas).
|
||||
- `top` (integer, opcional): Número máximo de planilhas a retornar. Mínimo: 1, Máximo: 999
|
||||
- `orderby` (string, opcional): Ordem de classificação (ex: 'position asc' para retornar planilhas na ordem das abas).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_worksheet">
|
||||
**Descrição:** Criar uma nova planilha (aba) em uma pasta de trabalho Excel armazenada em uma biblioteca de documentos do SharePoint. A nova planilha é adicionada no final da lista de abas.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `name` (string, obrigatório): Nome para a nova planilha. Máximo de 31 caracteres. Não pode conter: \ / * ? : [ ]. Deve ser único na pasta de trabalho.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_range_data">
|
||||
**Descrição:** Recuperar valores de células de um intervalo específico em uma planilha Excel armazenada no SharePoint. Para ler todos os dados sem saber as dimensões, use get_excel_used_range em vez disso.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha (aba) para leitura. Obtenha de get_excel_worksheets. Sensível a maiúsculas e minúsculas.
|
||||
- `range` (string, obrigatório): Intervalo de células em notação A1 (ex: 'A1:C10', 'A:C', '1:5', 'A1').
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/update_excel_range_data">
|
||||
**Descrição:** Escrever valores em um intervalo específico em uma planilha Excel armazenada no SharePoint. Sobrescreve o conteúdo existente das células. As dimensões do array de valores devem corresponder exatamente às dimensões do intervalo.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha (aba) a atualizar. Obtenha de get_excel_worksheets. Sensível a maiúsculas e minúsculas.
|
||||
- `range` (string, obrigatório): Intervalo de células em notação A1 onde os valores serão escritos (ex: 'A1:C3' para um bloco 3x3).
|
||||
- `values` (array, obrigatório): Array 2D de valores (linhas contendo células). Exemplo para A1:B2: [["Cabeçalho1", "Cabeçalho2"], ["Valor1", "Valor2"]]. Use null para limpar uma célula.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range_metadata">
|
||||
**Descrição:** Retornar apenas os metadados (endereço e dimensões) do intervalo utilizado em uma planilha, sem os valores reais das células. Ideal para arquivos grandes para entender o tamanho da planilha antes de ler dados em blocos.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha (aba) para leitura. Obtenha de get_excel_worksheets. Sensível a maiúsculas e minúsculas.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_used_range">
|
||||
**Descrição:** Recuperar todas as células contendo dados em uma planilha armazenada no SharePoint. Não use para arquivos maiores que 2MB. Para arquivos grandes, use get_excel_used_range_metadata primeiro, depois get_excel_range_data para ler em blocos menores.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha (aba) para leitura. Obtenha de get_excel_worksheets. Sensível a maiúsculas e minúsculas.
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'address,values,formulas,numberFormat,text,rowCount,columnCount').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_cell">
|
||||
**Descrição:** Recuperar o valor de uma única célula por índice de linha e coluna de um arquivo Excel no SharePoint. Os índices são baseados em 0 (linha 0 = linha 1 do Excel, coluna 0 = coluna A).
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha (aba). Obtenha de get_excel_worksheets. Sensível a maiúsculas e minúsculas.
|
||||
- `row` (integer, obrigatório): Índice de linha baseado em 0 (linha 0 = linha 1 do Excel). Intervalo válido: 0-1048575
|
||||
- `column` (integer, obrigatório): Índice de coluna baseado em 0 (coluna 0 = A, coluna 1 = B). Intervalo válido: 0-16383
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table">
|
||||
**Descrição:** Converter um intervalo de células em uma tabela Excel formatada com recursos de filtragem, classificação e dados estruturados. Tabelas habilitam add_excel_table_row para adicionar dados.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha contendo o intervalo de dados. Obtenha de get_excel_worksheets.
|
||||
- `range` (string, obrigatório): Intervalo de células para converter em tabela, incluindo cabeçalhos e dados (ex: 'A1:D10' onde A1:D1 contém cabeçalhos de coluna).
|
||||
- `has_headers` (boolean, opcional): Defina como true se a primeira linha contém cabeçalhos de coluna. Padrão: true
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_tables">
|
||||
**Descrição:** Listar todas as tabelas em uma planilha Excel específica armazenada no SharePoint. Retorna propriedades da tabela incluindo id, name, showHeaders e showTotals.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha para obter tabelas. Obtenha de get_excel_worksheets.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/add_excel_table_row">
|
||||
**Descrição:** Adicionar uma nova linha ao final de uma tabela Excel em um arquivo do SharePoint. O array de valores deve ter o mesmo número de elementos que o número de colunas da tabela.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha contendo a tabela. Obtenha de get_excel_worksheets.
|
||||
- `table_name` (string, obrigatório): Nome da tabela para adicionar a linha (ex: 'Table1'). Obtenha de get_excel_tables. Sensível a maiúsculas e minúsculas.
|
||||
- `values` (array, obrigatório): Array de valores de células para a nova linha, um por coluna na ordem da tabela (ex: ["João Silva", "joao@exemplo.com", 25]).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_excel_table_data">
|
||||
**Descrição:** Obter todas as linhas de uma tabela Excel em um arquivo do SharePoint como um intervalo de dados. Mais fácil do que get_excel_range_data ao trabalhar com tabelas estruturadas, pois não é necessário saber o intervalo exato.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha contendo a tabela. Obtenha de get_excel_worksheets.
|
||||
- `table_name` (string, obrigatório): Nome da tabela para obter dados (ex: 'Table1'). Obtenha de get_excel_tables. Sensível a maiúsculas e minúsculas.
|
||||
- `select` (string, opcional): Lista de propriedades separadas por vírgula para retornar (ex: 'address,values,formulas,numberFormat,text').
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/create_excel_chart">
|
||||
**Descrição:** Criar uma visualização de gráfico em uma planilha Excel armazenada no SharePoint a partir de um intervalo de dados. O gráfico é incorporado na planilha.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha onde o gráfico será criado. Obtenha de get_excel_worksheets.
|
||||
- `chart_type` (string, obrigatório): Tipo de gráfico (ex: 'ColumnClustered', 'ColumnStacked', 'Line', 'LineMarkers', 'Pie', 'Bar', 'BarClustered', 'Area', 'Scatter', 'Doughnut').
|
||||
- `source_data` (string, obrigatório): Intervalo de dados para o gráfico em notação A1, incluindo cabeçalhos (ex: 'A1:B10').
|
||||
- `series_by` (string, opcional): Como as séries de dados são organizadas: 'Auto', 'Columns' ou 'Rows'. Padrão: 'Auto'
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_charts">
|
||||
**Descrição:** Listar todos os gráficos incorporados em uma planilha Excel armazenada no SharePoint. Retorna propriedades do gráfico incluindo id, name, chartType, height, width e position.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha para listar gráficos. Obtenha de get_excel_worksheets.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_worksheet">
|
||||
**Descrição:** Remover permanentemente uma planilha (aba) e todo seu conteúdo de uma pasta de trabalho Excel armazenada no SharePoint. Não pode ser desfeito. Uma pasta de trabalho deve ter pelo menos uma planilha.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha a excluir. Sensível a maiúsculas e minúsculas. Todos os dados, tabelas e gráficos nesta planilha serão permanentemente removidos.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/delete_excel_table">
|
||||
**Descrição:** Remover uma tabela de uma planilha Excel no SharePoint. Isto exclui a estrutura da tabela (filtragem, formatação, recursos de tabela) mas preserva os dados subjacentes das células.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
- `worksheet_name` (string, obrigatório): Nome da planilha contendo a tabela. Obtenha de get_excel_worksheets.
|
||||
- `table_name` (string, obrigatório): Nome da tabela a excluir (ex: 'Table1'). Obtenha de get_excel_tables. Os dados nas células permanecerão após a exclusão da tabela.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/list_excel_names">
|
||||
**Descrição:** Recuperar todos os intervalos nomeados definidos em uma pasta de trabalho Excel armazenada no SharePoint. Intervalos nomeados são rótulos definidos pelo usuário para intervalos de células (ex: 'DadosVendas' para A1:D100).
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do arquivo Excel no SharePoint. Obtenha de list_files ou search_files.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_sharepoint/get_word_document_content">
|
||||
**Descrição:** Baixar e extrair conteúdo de texto de um documento Word (.docx) armazenado em uma biblioteca de documentos do SharePoint. Esta é a maneira recomendada de ler documentos Word do SharePoint.
|
||||
|
||||
**Parâmetros:**
|
||||
- `site_id` (string, obrigatório): O identificador completo do site SharePoint obtido de get_sites.
|
||||
- `drive_id` (string, obrigatório): O ID da biblioteca de documentos. Chame get_drives primeiro para obter IDs de drive válidos.
|
||||
- `item_id` (string, obrigatório): O identificador único do documento Word (.docx) no SharePoint. Obtenha de list_files ou search_files.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -107,6 +107,86 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `join_web_url` (string, obrigatório): A URL de participação na web da reunião a pesquisar.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/search_online_meetings_by_meeting_id">
|
||||
**Descrição:** Pesquisar reuniões online por ID externo da reunião.
|
||||
|
||||
**Parâmetros:**
|
||||
- `join_meeting_id` (string, obrigatório): O ID da reunião (código numérico) que os participantes usam para entrar. É o joinMeetingId exibido nos convites da reunião, não o meeting id da API Graph.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_meeting">
|
||||
**Descrição:** Obter detalhes de uma reunião online específica.
|
||||
|
||||
**Parâmetros:**
|
||||
- `meeting_id` (string, obrigatório): O ID da reunião na API Graph (string alfanumérica longa). Obter pelas ações create_meeting ou search_online_meetings. Diferente do joinMeetingId numérico.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_team_members">
|
||||
**Descrição:** Obter membros de uma equipe específica.
|
||||
|
||||
**Parâmetros:**
|
||||
- `team_id` (string, obrigatório): O identificador único da equipe. Obter pela ação get_teams.
|
||||
- `top` (integer, opcional): Número máximo de membros a recuperar por página (1-999). Padrão: 100.
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior. Quando a resposta incluir @odata.nextLink, extraia o valor do parâmetro $skiptoken e passe aqui para obter a próxima página de resultados.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/create_channel">
|
||||
**Descrição:** Criar um novo canal em uma equipe.
|
||||
|
||||
**Parâmetros:**
|
||||
- `team_id` (string, obrigatório): O identificador único da equipe. Obter pela ação get_teams.
|
||||
- `display_name` (string, obrigatório): Nome do canal exibido no Teams. Deve ser único na equipe. Máx 50 caracteres.
|
||||
- `description` (string, opcional): Descrição opcional explicando o propósito do canal. Visível nos detalhes do canal. Máx 1024 caracteres.
|
||||
- `membership_type` (string, opcional): Visibilidade do canal. Opções: standard, private. "standard" = visível para todos os membros da equipe, "private" = visível apenas para membros adicionados especificamente. Padrão: standard.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/get_message_replies">
|
||||
**Descrição:** Obter respostas a uma mensagem específica em um canal.
|
||||
|
||||
**Parâmetros:**
|
||||
- `team_id` (string, obrigatório): O identificador único da equipe. Obter pela ação get_teams.
|
||||
- `channel_id` (string, obrigatório): O identificador único do canal. Obter pela ação get_channels.
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem pai. Obter pela ação get_messages.
|
||||
- `top` (integer, opcional): Número máximo de respostas a recuperar por página (1-50). Padrão: 50.
|
||||
- `skip_token` (string, opcional): Token de paginação de uma resposta anterior. Quando a resposta incluir @odata.nextLink, extraia o valor do parâmetro $skiptoken e passe aqui para obter a próxima página de resultados.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/reply_to_message">
|
||||
**Descrição:** Responder a uma mensagem em um canal do Teams.
|
||||
|
||||
**Parâmetros:**
|
||||
- `team_id` (string, obrigatório): O identificador único da equipe. Obter pela ação get_teams.
|
||||
- `channel_id` (string, obrigatório): O identificador único do canal. Obter pela ação get_channels.
|
||||
- `message_id` (string, obrigatório): O identificador único da mensagem a responder. Obter pela ação get_messages.
|
||||
- `message` (string, obrigatório): O conteúdo da resposta. Para HTML, inclua tags de formatação. Para texto, use apenas texto simples.
|
||||
- `content_type` (string, opcional): Formato do conteúdo. Opções: html, text. "text" para texto simples, "html" para texto rico com formatação. Padrão: text.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/update_meeting">
|
||||
**Descrição:** Atualizar uma reunião online existente.
|
||||
|
||||
**Parâmetros:**
|
||||
- `meeting_id` (string, obrigatório): O identificador único da reunião. Obter pelas ações create_meeting ou search_online_meetings.
|
||||
- `subject` (string, opcional): Novo título da reunião.
|
||||
- `startDateTime` (string, opcional): Nova hora de início no formato ISO 8601 com fuso horário. Exemplo: "2024-01-20T10:00:00-08:00".
|
||||
- `endDateTime` (string, opcional): Nova hora de término no formato ISO 8601 com fuso horário.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_teams/delete_meeting">
|
||||
**Descrição:** Excluir uma reunião online.
|
||||
|
||||
**Parâmetros:**
|
||||
- `meeting_id` (string, obrigatório): O identificador único da reunião a excluir. Obter pelas ações create_meeting ou search_online_meetings.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -97,6 +97,26 @@ CREWAI_PLATFORM_INTEGRATION_TOKEN=seu_enterprise_token
|
||||
- `file_id` (string, obrigatório): O ID do documento a excluir.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/copy_document">
|
||||
**Descrição:** Copiar um documento para um novo local no OneDrive.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_id` (string, obrigatório): O ID do documento a copiar.
|
||||
- `name` (string, opcional): Novo nome para o documento copiado.
|
||||
- `parent_id` (string, opcional): O ID da pasta de destino (padrão: raiz).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="microsoft_word/move_document">
|
||||
**Descrição:** Mover um documento para um novo local no OneDrive.
|
||||
|
||||
**Parâmetros:**
|
||||
- `file_id` (string, obrigatório): O ID do documento a mover.
|
||||
- `parent_id` (string, obrigatório): O ID da pasta de destino.
|
||||
- `name` (string, opcional): Novo nome para o documento movido.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exemplos de Uso
|
||||
|
||||
@@ -82,7 +82,7 @@ CrewAI AMP expande o poder do framework open-source com funcionalidades projetad
|
||||
<Card
|
||||
title="Implantar Crew"
|
||||
icon="rocket"
|
||||
href="/pt-BR/enterprise/guides/deploy-crew"
|
||||
href="/pt-BR/enterprise/guides/deploy-to-amp"
|
||||
>
|
||||
Implantar Crew
|
||||
</Card>
|
||||
@@ -92,11 +92,11 @@ CrewAI AMP expande o poder do framework open-source com funcionalidades projetad
|
||||
<Card
|
||||
title="Acesso via API"
|
||||
icon="code"
|
||||
href="/pt-BR/enterprise/guides/deploy-crew"
|
||||
href="/pt-BR/enterprise/guides/kickoff-crew"
|
||||
>
|
||||
Usar a API do Crew
|
||||
</Card>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Para instruções detalhadas, consulte nosso [guia de implantação](/pt-BR/enterprise/guides/deploy-crew) ou clique no botão abaixo para começar.
|
||||
Para instruções detalhadas, consulte nosso [guia de implantação](/pt-BR/enterprise/guides/deploy-to-amp) ou clique no botão abaixo para começar.
|
||||
|
||||
@@ -112,3 +112,9 @@ Workflows HITL são particularmente valiosos para:
|
||||
- Operações sensíveis ou de alto risco
|
||||
- Tarefas criativas que requerem julgamento humano
|
||||
- Revisões de conformidade e regulamentação
|
||||
|
||||
## Recursos Enterprise
|
||||
|
||||
<Card title="Plataforma de Gerenciamento HITL para Flows" icon="users-gear" href="/pt-BR/enterprise/features/flow-hitl-management">
|
||||
O CrewAI Enterprise oferece um sistema abrangente de gerenciamento HITL para Flows com revisão na plataforma, atribuição de respondentes, permissões, políticas de escalação, gerenciamento de SLA, roteamento dinâmico e análises completas. [Saiba mais →](/pt-BR/enterprise/features/flow-hitl-management)
|
||||
</Card>
|
||||
|
||||
115
docs/pt-BR/observability/galileo.mdx
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: Galileo Galileu
|
||||
description: Integração Galileo para rastreamento e avaliação CrewAI
|
||||
icon: telescope
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Visão geral
|
||||
|
||||
Este guia demonstra como integrar o **Galileo**com o **CrewAI**
|
||||
para rastreamento abrangente e engenharia de avaliação.
|
||||
Ao final deste guia, você será capaz de rastrear seus agentes CrewAI,
|
||||
monitorar seu desempenho e avaliar seu comportamento com
|
||||
A poderosa plataforma de observabilidade do Galileo.
|
||||
|
||||
> **O que é Galileo?**[Galileo](https://galileo.ai/) é avaliação e observabilidade de IA
|
||||
plataforma que oferece rastreamento, avaliação e
|
||||
e monitoramento de aplicações de IA. Ele permite que as equipes capturem a verdade,
|
||||
criar grades de proteção robustas e realizar experimentos sistemáticos com
|
||||
rastreamento de experimentos integrado e análise de desempenho -garantindo confiabilidade,
|
||||
transparência e melhoria contínua em todo o ciclo de vida da IA.
|
||||
|
||||
## Primeiros passos
|
||||
|
||||
Este tutorial segue o [CrewAI Quickstart](pt-BR/quickstart) e mostra como adicionar
|
||||
[CrewAIEventListener] do Galileo(https://v2docs.galileo.ai/sdk-api/python/reference/handlers/crewai/handler),
|
||||
um manipulador de eventos.
|
||||
Para mais informações, consulte Galileu
|
||||
[Adicionar Galileo a um aplicativo CrewAI](https://v2docs.galileo.ai/how-to-guides/third-party-integrations/add-galileo-to-crewai/add-galileo-to-crewai)
|
||||
guia prático.
|
||||
|
||||
> **Observação**Este tutorial pressupõe que você concluiu o [CrewAI Quickstart](pt-BR/quickstart).
|
||||
Se você quiser um exemplo completo e abrangente, consulte o Galileo
|
||||
[Repositório de exemplo SDK da CrewAI](https://github.com/rungalileo/sdk-examples/tree/main/python/agent/crew-ai).
|
||||
|
||||
### Etapa 1: instalar dependências
|
||||
|
||||
Instale as dependências necessárias para seu aplicativo.
|
||||
Crie um ambiente virtual usando seu método preferido,
|
||||
em seguida, instale dependências dentro desse ambiente usando seu
|
||||
ferramenta preferida:
|
||||
|
||||
```bash
|
||||
uv add galileo
|
||||
```
|
||||
|
||||
### Etapa 2: adicione ao arquivo .env do [CrewAI Quickstart](/pt-BR/quickstart)
|
||||
|
||||
```bash
|
||||
# Your Galileo API key
|
||||
GALILEO_API_KEY="your-galileo-api-key"
|
||||
|
||||
# Your Galileo project name
|
||||
GALILEO_PROJECT="your-galileo-project-name"
|
||||
|
||||
# The name of the Log stream you want to use for logging
|
||||
GALILEO_LOG_STREAM="your-galileo-log-stream "
|
||||
```
|
||||
|
||||
### Etapa 3: adicionar o ouvinte de eventos Galileo
|
||||
|
||||
Para habilitar o registro com Galileo, você precisa criar uma instância do `CrewAIEventListener`.
|
||||
Importe o pacote manipulador Galileo CrewAI por
|
||||
adicionando o seguinte código no topo do seu arquivo main.py:
|
||||
|
||||
```python
|
||||
from galileo.handlers.crewai.handler import CrewAIEventListener
|
||||
```
|
||||
|
||||
No início da sua função run, crie o ouvinte de evento:
|
||||
|
||||
```python
|
||||
def run():
|
||||
# Create the event listener
|
||||
CrewAIEventListener()
|
||||
# The rest of your existing code goes here
|
||||
```
|
||||
|
||||
Quando você cria a instância do listener, ela é automaticamente
|
||||
registrado na CrewAI.
|
||||
|
||||
### Etapa 4: administre sua Crew
|
||||
|
||||
Administre sua Crew com o CrewAI CLI:
|
||||
|
||||
```bash
|
||||
crewai run
|
||||
```
|
||||
|
||||
### Passo 5: Visualize os traços no Galileo
|
||||
|
||||
Assim que sua tripulação terminar, os rastros serão eliminados e aparecerão no Galileo.
|
||||
|
||||

|
||||
|
||||
## Compreendendo a integração do Galileo
|
||||
|
||||
Galileo se integra ao CrewAI registrando um ouvinte de evento
|
||||
que captura eventos de execução da tripulação (por exemplo, ações do agente, chamadas de ferramentas, respostas do modelo)
|
||||
e os encaminha ao Galileo para observabilidade e avaliação.
|
||||
|
||||
### Compreendendo o ouvinte de eventos
|
||||
|
||||
Criar uma instância `CrewAIEventListener()` é tudo o que você precisa
|
||||
necessário para habilitar o Galileo para uma execução do CrewAI. Quando instanciado, o ouvinte:
|
||||
|
||||
-Registra-se automaticamente no CrewAI
|
||||
-Lê a configuração do Galileo a partir de variáveis de ambiente
|
||||
-Registra todos os dados de execução no projeto Galileo e fluxo de log especificado por
|
||||
`GALILEO_PROJECT` e `GALILEO_LOG_STREAM`
|
||||
|
||||
Nenhuma configuração adicional ou alterações de código são necessárias.
|
||||
Todos os dados desta execução são registados no projecto Galileo e
|
||||
fluxo de log especificado pela configuração do seu ambiente
|
||||
(por exemplo, GALILEO_PROJECT e GALILEO_LOG_STREAM).
|
||||
43
lib/crewai-files/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# crewai-files
|
||||
|
||||
File handling utilities for CrewAI multimodal inputs.
|
||||
|
||||
## Supported File Types
|
||||
|
||||
- `ImageFile` - PNG, JPEG, GIF, WebP
|
||||
- `PDFFile` - PDF documents
|
||||
- `TextFile` - Plain text files
|
||||
- `AudioFile` - MP3, WAV, FLAC, OGG, M4A
|
||||
- `VideoFile` - MP4, WebM, MOV, AVI
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from crewai_files import File, ImageFile, PDFFile
|
||||
|
||||
# Auto-detect file type
|
||||
file = File(source="document.pdf") # Resolves to PDFFile
|
||||
|
||||
# Or use specific types
|
||||
image = ImageFile(source="chart.png")
|
||||
pdf = PDFFile(source="report.pdf")
|
||||
```
|
||||
|
||||
### Passing Files to Crews
|
||||
|
||||
```python
|
||||
crew.kickoff(
|
||||
input_files={"chart": ImageFile(source="chart.png")}
|
||||
)
|
||||
```
|
||||
|
||||
### Passing Files to Tasks
|
||||
|
||||
```python
|
||||
task = Task(
|
||||
description="Analyze the chart",
|
||||
expected_output="Analysis",
|
||||
agent=agent,
|
||||
input_files=[ImageFile(source="chart.png")],
|
||||
)
|
||||
```
|
||||
25
lib/crewai-files/pyproject.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
[project]
|
||||
name = "crewai-files"
|
||||
dynamic = ["version"]
|
||||
description = "File handling utilities for CrewAI multimodal inputs"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
{ name = "Greyson LaLonde", email = "greyson@crewai.com" }
|
||||
]
|
||||
requires-python = ">=3.10, <3.14"
|
||||
dependencies = [
|
||||
"Pillow~=10.4.0",
|
||||
"pypdf~=4.0.0",
|
||||
"python-magic>=0.4.27",
|
||||
"aiocache~=0.12.3",
|
||||
"aiofiles~=24.1.0",
|
||||
"tinytag~=1.10.0",
|
||||
"av~=13.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.version]
|
||||
path = "src/crewai_files/__init__.py"
|
||||
155
lib/crewai-files/src/crewai_files/__init__.py
Normal file
@@ -0,0 +1,155 @@
|
||||
"""File handling utilities for crewAI tasks."""
|
||||
|
||||
from crewai_files.cache.cleanup import (
|
||||
cleanup_expired_files,
|
||||
cleanup_provider_files,
|
||||
cleanup_uploaded_files,
|
||||
)
|
||||
from crewai_files.cache.upload_cache import (
|
||||
CachedUpload,
|
||||
UploadCache,
|
||||
get_upload_cache,
|
||||
reset_upload_cache,
|
||||
)
|
||||
from crewai_files.core.resolved import (
|
||||
FileReference,
|
||||
InlineBase64,
|
||||
InlineBytes,
|
||||
ResolvedFile,
|
||||
ResolvedFileType,
|
||||
UrlReference,
|
||||
)
|
||||
from crewai_files.core.sources import (
|
||||
FileBytes,
|
||||
FilePath,
|
||||
FileSource,
|
||||
FileSourceInput,
|
||||
FileStream,
|
||||
FileUrl,
|
||||
RawFileInput,
|
||||
)
|
||||
from crewai_files.core.types import (
|
||||
AudioExtension,
|
||||
AudioFile,
|
||||
AudioMimeType,
|
||||
BaseFile,
|
||||
File,
|
||||
FileInput,
|
||||
FileMode,
|
||||
ImageExtension,
|
||||
ImageFile,
|
||||
ImageMimeType,
|
||||
PDFContentType,
|
||||
PDFExtension,
|
||||
PDFFile,
|
||||
TextContentType,
|
||||
TextExtension,
|
||||
TextFile,
|
||||
VideoExtension,
|
||||
VideoFile,
|
||||
VideoMimeType,
|
||||
)
|
||||
from crewai_files.formatting import (
|
||||
aformat_multimodal_content,
|
||||
format_multimodal_content,
|
||||
)
|
||||
from crewai_files.processing import (
|
||||
ANTHROPIC_CONSTRAINTS,
|
||||
BEDROCK_CONSTRAINTS,
|
||||
GEMINI_CONSTRAINTS,
|
||||
OPENAI_CONSTRAINTS,
|
||||
AudioConstraints,
|
||||
FileHandling,
|
||||
FileProcessingError,
|
||||
FileProcessor,
|
||||
FileTooLargeError,
|
||||
FileValidationError,
|
||||
ImageConstraints,
|
||||
PDFConstraints,
|
||||
ProcessingDependencyError,
|
||||
ProviderConstraints,
|
||||
UnsupportedFileTypeError,
|
||||
VideoConstraints,
|
||||
get_constraints_for_provider,
|
||||
get_supported_content_types,
|
||||
)
|
||||
from crewai_files.resolution.resolver import (
|
||||
FileResolver,
|
||||
FileResolverConfig,
|
||||
create_resolver,
|
||||
)
|
||||
from crewai_files.resolution.utils import normalize_input_files, wrap_file_source
|
||||
from crewai_files.uploaders import FileUploader, UploadResult, get_uploader
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ANTHROPIC_CONSTRAINTS",
|
||||
"BEDROCK_CONSTRAINTS",
|
||||
"GEMINI_CONSTRAINTS",
|
||||
"OPENAI_CONSTRAINTS",
|
||||
"AudioConstraints",
|
||||
"AudioExtension",
|
||||
"AudioFile",
|
||||
"AudioMimeType",
|
||||
"BaseFile",
|
||||
"CachedUpload",
|
||||
"File",
|
||||
"FileBytes",
|
||||
"FileHandling",
|
||||
"FileInput",
|
||||
"FileMode",
|
||||
"FilePath",
|
||||
"FileProcessingError",
|
||||
"FileProcessor",
|
||||
"FileReference",
|
||||
"FileResolver",
|
||||
"FileResolverConfig",
|
||||
"FileSource",
|
||||
"FileSourceInput",
|
||||
"FileStream",
|
||||
"FileTooLargeError",
|
||||
"FileUploader",
|
||||
"FileUrl",
|
||||
"FileValidationError",
|
||||
"ImageConstraints",
|
||||
"ImageExtension",
|
||||
"ImageFile",
|
||||
"ImageMimeType",
|
||||
"InlineBase64",
|
||||
"InlineBytes",
|
||||
"PDFConstraints",
|
||||
"PDFContentType",
|
||||
"PDFExtension",
|
||||
"PDFFile",
|
||||
"ProcessingDependencyError",
|
||||
"ProviderConstraints",
|
||||
"RawFileInput",
|
||||
"ResolvedFile",
|
||||
"ResolvedFileType",
|
||||
"TextContentType",
|
||||
"TextExtension",
|
||||
"TextFile",
|
||||
"UnsupportedFileTypeError",
|
||||
"UploadCache",
|
||||
"UploadResult",
|
||||
"UrlReference",
|
||||
"VideoConstraints",
|
||||
"VideoExtension",
|
||||
"VideoFile",
|
||||
"VideoMimeType",
|
||||
"aformat_multimodal_content",
|
||||
"cleanup_expired_files",
|
||||
"cleanup_provider_files",
|
||||
"cleanup_uploaded_files",
|
||||
"create_resolver",
|
||||
"format_multimodal_content",
|
||||
"get_constraints_for_provider",
|
||||
"get_supported_content_types",
|
||||
"get_upload_cache",
|
||||
"get_uploader",
|
||||
"normalize_input_files",
|
||||
"reset_upload_cache",
|
||||
"wrap_file_source",
|
||||
]
|
||||
|
||||
__version__ = "1.9.3"
|
||||
14
lib/crewai-files/src/crewai_files/cache/__init__.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"""Upload caching and cleanup."""
|
||||
|
||||
from crewai_files.cache.cleanup import cleanup_uploaded_files
|
||||
from crewai_files.cache.metrics import FileOperationMetrics, measure_operation
|
||||
from crewai_files.cache.upload_cache import UploadCache, get_upload_cache
|
||||
|
||||
|
||||
__all__ = [
|
||||
"FileOperationMetrics",
|
||||
"UploadCache",
|
||||
"cleanup_uploaded_files",
|
||||
"get_upload_cache",
|
||||
"measure_operation",
|
||||
]
|
||||
374
lib/crewai-files/src/crewai_files/cache/cleanup.py
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
"""Cleanup utilities for uploaded files."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from crewai_files.cache.upload_cache import CachedUpload, UploadCache
|
||||
from crewai_files.uploaders import get_uploader
|
||||
from crewai_files.uploaders.factory import ProviderType
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from crewai_files.uploaders.base import FileUploader
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _safe_delete(
|
||||
uploader: FileUploader,
|
||||
file_id: str,
|
||||
provider: str,
|
||||
) -> bool:
|
||||
"""Safely delete a file, logging any errors.
|
||||
|
||||
Args:
|
||||
uploader: The file uploader to use.
|
||||
file_id: The file ID to delete.
|
||||
provider: Provider name for logging.
|
||||
|
||||
Returns:
|
||||
True if deleted successfully, False otherwise.
|
||||
"""
|
||||
try:
|
||||
if uploader.delete(file_id):
|
||||
logger.debug(f"Deleted {file_id} from {provider}")
|
||||
return True
|
||||
logger.warning(f"Failed to delete {file_id} from {provider}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.warning(f"Error deleting {file_id} from {provider}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def cleanup_uploaded_files(
|
||||
cache: UploadCache,
|
||||
*,
|
||||
delete_from_provider: bool = True,
|
||||
providers: list[ProviderType] | None = None,
|
||||
) -> int:
|
||||
"""Clean up uploaded files from the cache and optionally from providers.
|
||||
|
||||
Args:
|
||||
cache: The upload cache to clean up.
|
||||
delete_from_provider: If True, delete files from the provider as well.
|
||||
providers: Optional list of providers to clean up. If None, cleans all.
|
||||
|
||||
Returns:
|
||||
Number of files cleaned up.
|
||||
"""
|
||||
cleaned = 0
|
||||
|
||||
provider_uploads: dict[ProviderType, list[CachedUpload]] = {}
|
||||
|
||||
for provider in _get_providers_from_cache(cache):
|
||||
if providers is not None and provider not in providers:
|
||||
continue
|
||||
provider_uploads[provider] = cache.get_all_for_provider(provider)
|
||||
|
||||
if delete_from_provider:
|
||||
for provider, uploads in provider_uploads.items():
|
||||
uploader = get_uploader(provider)
|
||||
if uploader is None:
|
||||
logger.warning(
|
||||
f"No uploader available for {provider}, skipping cleanup"
|
||||
)
|
||||
continue
|
||||
|
||||
for upload in uploads:
|
||||
if _safe_delete(uploader, upload.file_id, provider):
|
||||
cleaned += 1
|
||||
|
||||
cache.clear()
|
||||
|
||||
logger.info(f"Cleaned up {cleaned} uploaded files")
|
||||
return cleaned
|
||||
|
||||
|
||||
def cleanup_expired_files(
|
||||
cache: UploadCache,
|
||||
*,
|
||||
delete_from_provider: bool = False,
|
||||
) -> int:
|
||||
"""Clean up expired files from the cache.
|
||||
|
||||
Args:
|
||||
cache: The upload cache to clean up.
|
||||
delete_from_provider: If True, attempt to delete from provider as well.
|
||||
Note: Expired files may already be deleted by the provider.
|
||||
|
||||
Returns:
|
||||
Number of expired entries removed from cache.
|
||||
"""
|
||||
expired_entries: list[CachedUpload] = []
|
||||
|
||||
if delete_from_provider:
|
||||
for provider in _get_providers_from_cache(cache):
|
||||
expired_entries.extend(
|
||||
upload
|
||||
for upload in cache.get_all_for_provider(provider)
|
||||
if upload.is_expired()
|
||||
)
|
||||
|
||||
removed = cache.clear_expired()
|
||||
|
||||
if delete_from_provider:
|
||||
for upload in expired_entries:
|
||||
uploader = get_uploader(upload.provider)
|
||||
if uploader is not None:
|
||||
try:
|
||||
uploader.delete(upload.file_id)
|
||||
except Exception as e:
|
||||
logger.debug(f"Could not delete expired file {upload.file_id}: {e}")
|
||||
|
||||
return removed
|
||||
|
||||
|
||||
def cleanup_provider_files(
|
||||
provider: ProviderType,
|
||||
*,
|
||||
cache: UploadCache | None = None,
|
||||
delete_all_from_provider: bool = False,
|
||||
) -> int:
|
||||
"""Clean up all files for a specific provider.
|
||||
|
||||
Args:
|
||||
provider: Provider name to clean up.
|
||||
cache: Optional upload cache to clear entries from.
|
||||
delete_all_from_provider: If True, delete all files from the provider,
|
||||
not just cached ones.
|
||||
|
||||
Returns:
|
||||
Number of files deleted.
|
||||
"""
|
||||
deleted = 0
|
||||
uploader = get_uploader(provider)
|
||||
|
||||
if uploader is None:
|
||||
logger.warning(f"No uploader available for {provider}")
|
||||
return 0
|
||||
|
||||
if delete_all_from_provider:
|
||||
try:
|
||||
files = uploader.list_files()
|
||||
for file_info in files:
|
||||
file_id = file_info.get("id") or file_info.get("name")
|
||||
if file_id and uploader.delete(file_id):
|
||||
deleted += 1
|
||||
except Exception as e:
|
||||
logger.warning(f"Error listing/deleting files from {provider}: {e}")
|
||||
elif cache is not None:
|
||||
uploads = cache.get_all_for_provider(provider)
|
||||
for upload in uploads:
|
||||
if _safe_delete(uploader, upload.file_id, provider):
|
||||
deleted += 1
|
||||
cache.remove_by_file_id(upload.file_id, provider)
|
||||
|
||||
logger.info(f"Deleted {deleted} files from {provider}")
|
||||
return deleted
|
||||
|
||||
|
||||
def _get_providers_from_cache(cache: UploadCache) -> set[ProviderType]:
|
||||
"""Get unique provider names from cache entries.
|
||||
|
||||
Args:
|
||||
cache: The upload cache.
|
||||
|
||||
Returns:
|
||||
Set of provider names.
|
||||
"""
|
||||
return cache.get_providers()
|
||||
|
||||
|
||||
async def _asafe_delete(
|
||||
uploader: FileUploader,
|
||||
file_id: str,
|
||||
provider: str,
|
||||
) -> bool:
|
||||
"""Async safely delete a file, logging any errors.
|
||||
|
||||
Args:
|
||||
uploader: The file uploader to use.
|
||||
file_id: The file ID to delete.
|
||||
provider: Provider name for logging.
|
||||
|
||||
Returns:
|
||||
True if deleted successfully, False otherwise.
|
||||
"""
|
||||
try:
|
||||
if await uploader.adelete(file_id):
|
||||
logger.debug(f"Deleted {file_id} from {provider}")
|
||||
return True
|
||||
logger.warning(f"Failed to delete {file_id} from {provider}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.warning(f"Error deleting {file_id} from {provider}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def acleanup_uploaded_files(
|
||||
cache: UploadCache,
|
||||
*,
|
||||
delete_from_provider: bool = True,
|
||||
providers: list[ProviderType] | None = None,
|
||||
max_concurrency: int = 10,
|
||||
) -> int:
|
||||
"""Async clean up uploaded files from the cache and optionally from providers.
|
||||
|
||||
Args:
|
||||
cache: The upload cache to clean up.
|
||||
delete_from_provider: If True, delete files from the provider as well.
|
||||
providers: Optional list of providers to clean up. If None, cleans all.
|
||||
max_concurrency: Maximum number of concurrent delete operations.
|
||||
|
||||
Returns:
|
||||
Number of files cleaned up.
|
||||
"""
|
||||
cleaned = 0
|
||||
|
||||
provider_uploads: dict[ProviderType, list[CachedUpload]] = {}
|
||||
|
||||
for provider in _get_providers_from_cache(cache):
|
||||
if providers is not None and provider not in providers:
|
||||
continue
|
||||
provider_uploads[provider] = await cache.aget_all_for_provider(provider)
|
||||
|
||||
if delete_from_provider:
|
||||
semaphore = asyncio.Semaphore(max_concurrency)
|
||||
|
||||
async def delete_one(file_uploader: FileUploader, cached: CachedUpload) -> bool:
|
||||
"""Delete a single file with semaphore limiting."""
|
||||
async with semaphore:
|
||||
return await _asafe_delete(
|
||||
file_uploader, cached.file_id, cached.provider
|
||||
)
|
||||
|
||||
tasks: list[asyncio.Task[bool]] = []
|
||||
for provider, uploads in provider_uploads.items():
|
||||
uploader = get_uploader(provider)
|
||||
if uploader is None:
|
||||
logger.warning(
|
||||
f"No uploader available for {provider}, skipping cleanup"
|
||||
)
|
||||
continue
|
||||
|
||||
tasks.extend(
|
||||
asyncio.create_task(delete_one(uploader, cached)) for cached in uploads
|
||||
)
|
||||
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
cleaned = sum(1 for r in results if r is True)
|
||||
|
||||
await cache.aclear()
|
||||
|
||||
logger.info(f"Cleaned up {cleaned} uploaded files")
|
||||
return cleaned
|
||||
|
||||
|
||||
async def acleanup_expired_files(
|
||||
cache: UploadCache,
|
||||
*,
|
||||
delete_from_provider: bool = False,
|
||||
max_concurrency: int = 10,
|
||||
) -> int:
|
||||
"""Async clean up expired files from the cache.
|
||||
|
||||
Args:
|
||||
cache: The upload cache to clean up.
|
||||
delete_from_provider: If True, attempt to delete from provider as well.
|
||||
max_concurrency: Maximum number of concurrent delete operations.
|
||||
|
||||
Returns:
|
||||
Number of expired entries removed from cache.
|
||||
"""
|
||||
expired_entries: list[CachedUpload] = []
|
||||
|
||||
if delete_from_provider:
|
||||
for provider in _get_providers_from_cache(cache):
|
||||
uploads = await cache.aget_all_for_provider(provider)
|
||||
expired_entries.extend(upload for upload in uploads if upload.is_expired())
|
||||
|
||||
removed = await cache.aclear_expired()
|
||||
|
||||
if delete_from_provider and expired_entries:
|
||||
semaphore = asyncio.Semaphore(max_concurrency)
|
||||
|
||||
async def delete_expired(cached: CachedUpload) -> None:
|
||||
"""Delete an expired file with semaphore limiting."""
|
||||
async with semaphore:
|
||||
file_uploader = get_uploader(cached.provider)
|
||||
if file_uploader is not None:
|
||||
try:
|
||||
await file_uploader.adelete(cached.file_id)
|
||||
except Exception as e:
|
||||
logger.debug(
|
||||
f"Could not delete expired file {cached.file_id}: {e}"
|
||||
)
|
||||
|
||||
await asyncio.gather(
|
||||
*[delete_expired(cached) for cached in expired_entries],
|
||||
return_exceptions=True,
|
||||
)
|
||||
|
||||
return removed
|
||||
|
||||
|
||||
async def acleanup_provider_files(
|
||||
provider: ProviderType,
|
||||
*,
|
||||
cache: UploadCache | None = None,
|
||||
delete_all_from_provider: bool = False,
|
||||
max_concurrency: int = 10,
|
||||
) -> int:
|
||||
"""Async clean up all files for a specific provider.
|
||||
|
||||
Args:
|
||||
provider: Provider name to clean up.
|
||||
cache: Optional upload cache to clear entries from.
|
||||
delete_all_from_provider: If True, delete all files from the provider.
|
||||
max_concurrency: Maximum number of concurrent delete operations.
|
||||
|
||||
Returns:
|
||||
Number of files deleted.
|
||||
"""
|
||||
deleted = 0
|
||||
uploader = get_uploader(provider)
|
||||
|
||||
if uploader is None:
|
||||
logger.warning(f"No uploader available for {provider}")
|
||||
return 0
|
||||
|
||||
semaphore = asyncio.Semaphore(max_concurrency)
|
||||
|
||||
async def delete_single(target_file_id: str) -> bool:
|
||||
"""Delete a single file with semaphore limiting."""
|
||||
async with semaphore:
|
||||
return await uploader.adelete(target_file_id)
|
||||
|
||||
if delete_all_from_provider:
|
||||
try:
|
||||
files = uploader.list_files()
|
||||
tasks = []
|
||||
for file_info in files:
|
||||
fid = file_info.get("id") or file_info.get("name")
|
||||
if fid:
|
||||
tasks.append(delete_single(fid))
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
deleted = sum(1 for r in results if r is True)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error listing/deleting files from {provider}: {e}")
|
||||
elif cache is not None:
|
||||
uploads = await cache.aget_all_for_provider(provider)
|
||||
tasks = []
|
||||
for upload in uploads:
|
||||
tasks.append(delete_single(upload.file_id))
|
||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||
for upload, result in zip(uploads, results, strict=False):
|
||||
if result is True:
|
||||
deleted += 1
|
||||
await cache.aremove_by_file_id(upload.file_id, provider)
|
||||
|
||||
logger.info(f"Deleted {deleted} files from {provider}")
|
||||
return deleted
|
||||
184
lib/crewai-files/src/crewai_files/cache/metrics.py
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
"""Performance metrics and structured logging for file operations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
import logging
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FileOperationMetrics:
|
||||
"""Metrics for a file operation.
|
||||
|
||||
Attributes:
|
||||
operation: Name of the operation (e.g., "upload", "resolve", "process").
|
||||
filename: Name of the file being operated on.
|
||||
provider: Provider name if applicable.
|
||||
duration_ms: Duration of the operation in milliseconds.
|
||||
size_bytes: Size of the file in bytes.
|
||||
success: Whether the operation succeeded.
|
||||
error: Error message if operation failed.
|
||||
timestamp: When the operation occurred.
|
||||
metadata: Additional operation-specific metadata.
|
||||
"""
|
||||
|
||||
operation: str
|
||||
filename: str | None = None
|
||||
provider: str | None = None
|
||||
duration_ms: float = 0.0
|
||||
size_bytes: int | None = None
|
||||
success: bool = True
|
||||
error: str | None = None
|
||||
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
metadata: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""Convert metrics to dictionary for logging.
|
||||
|
||||
Returns:
|
||||
Dictionary representation of metrics.
|
||||
"""
|
||||
result: dict[str, Any] = {
|
||||
"operation": self.operation,
|
||||
"duration_ms": round(self.duration_ms, 2),
|
||||
"success": self.success,
|
||||
"timestamp": self.timestamp.isoformat(),
|
||||
}
|
||||
|
||||
if self.filename:
|
||||
result["file_name"] = self.filename
|
||||
if self.provider:
|
||||
result["provider"] = self.provider
|
||||
if self.size_bytes is not None:
|
||||
result["size_bytes"] = self.size_bytes
|
||||
if self.error:
|
||||
result["error"] = self.error
|
||||
if self.metadata:
|
||||
result.update(self.metadata)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@contextmanager
|
||||
def measure_operation(
|
||||
operation: str,
|
||||
*,
|
||||
filename: str | None = None,
|
||||
provider: str | None = None,
|
||||
size_bytes: int | None = None,
|
||||
log_level: int = logging.DEBUG,
|
||||
**extra_metadata: Any,
|
||||
) -> Generator[FileOperationMetrics, None, None]:
|
||||
"""Context manager to measure and log operation performance.
|
||||
|
||||
Args:
|
||||
operation: Name of the operation.
|
||||
filename: Optional filename being operated on.
|
||||
provider: Optional provider name.
|
||||
size_bytes: Optional file size in bytes.
|
||||
log_level: Log level for the result message.
|
||||
**extra_metadata: Additional metadata to include.
|
||||
|
||||
Yields:
|
||||
FileOperationMetrics object that will be populated with results.
|
||||
|
||||
Example:
|
||||
with measure_operation("upload", filename="test.pdf", provider="openai") as metrics:
|
||||
result = upload_file(file)
|
||||
metrics.metadata["file_id"] = result.file_id
|
||||
"""
|
||||
metrics = FileOperationMetrics(
|
||||
operation=operation,
|
||||
filename=filename,
|
||||
provider=provider,
|
||||
size_bytes=size_bytes,
|
||||
metadata=dict(extra_metadata),
|
||||
)
|
||||
|
||||
start_time = time.perf_counter()
|
||||
|
||||
try:
|
||||
yield metrics
|
||||
metrics.success = True
|
||||
except Exception as e:
|
||||
metrics.success = False
|
||||
metrics.error = str(e)
|
||||
raise
|
||||
finally:
|
||||
metrics.duration_ms = (time.perf_counter() - start_time) * 1000
|
||||
|
||||
log_message = f"{operation}"
|
||||
if filename:
|
||||
log_message += f" [{filename}]"
|
||||
if provider:
|
||||
log_message += f" ({provider})"
|
||||
|
||||
if metrics.success:
|
||||
log_message += f" completed in {metrics.duration_ms:.2f}ms"
|
||||
else:
|
||||
log_message += f" failed after {metrics.duration_ms:.2f}ms: {metrics.error}"
|
||||
|
||||
logger.log(log_level, log_message, extra=metrics.to_dict())
|
||||
|
||||
|
||||
def log_file_operation(
|
||||
operation: str,
|
||||
*,
|
||||
filename: str | None = None,
|
||||
provider: str | None = None,
|
||||
size_bytes: int | None = None,
|
||||
duration_ms: float | None = None,
|
||||
success: bool = True,
|
||||
error: str | None = None,
|
||||
level: int = logging.INFO,
|
||||
**extra: Any,
|
||||
) -> None:
|
||||
"""Log a file operation with structured data.
|
||||
|
||||
Args:
|
||||
operation: Name of the operation.
|
||||
filename: Optional filename being operated on.
|
||||
provider: Optional provider name.
|
||||
size_bytes: Optional file size in bytes.
|
||||
duration_ms: Optional duration in milliseconds.
|
||||
success: Whether the operation succeeded.
|
||||
error: Optional error message.
|
||||
level: Log level to use.
|
||||
**extra: Additional metadata to include.
|
||||
"""
|
||||
metrics = FileOperationMetrics(
|
||||
operation=operation,
|
||||
filename=filename,
|
||||
provider=provider,
|
||||
size_bytes=size_bytes,
|
||||
duration_ms=duration_ms or 0.0,
|
||||
success=success,
|
||||
error=error,
|
||||
metadata=dict(extra),
|
||||
)
|
||||
|
||||
message = f"{operation}"
|
||||
if filename:
|
||||
message += f" [{filename}]"
|
||||
if provider:
|
||||
message += f" ({provider})"
|
||||
|
||||
if success:
|
||||
if duration_ms:
|
||||
message += f" completed in {duration_ms:.2f}ms"
|
||||
else:
|
||||
message += " completed"
|
||||
else:
|
||||
message += " failed"
|
||||
if error:
|
||||
message += f": {error}"
|
||||
|
||||
logger.log(level, message, extra=metrics.to_dict())
|
||||
553
lib/crewai-files/src/crewai_files/cache/upload_cache.py
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
"""Cache for tracking uploaded files using aiocache."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import atexit
|
||||
import builtins
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
import hashlib
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from aiocache import Cache # type: ignore[import-untyped]
|
||||
from aiocache.serializers import PickleSerializer # type: ignore[import-untyped]
|
||||
|
||||
from crewai_files.core.constants import DEFAULT_MAX_CACHE_ENTRIES, DEFAULT_TTL_SECONDS
|
||||
from crewai_files.uploaders.factory import ProviderType
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from crewai_files.core.types import FileInput
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CachedUpload:
|
||||
"""Represents a cached file upload.
|
||||
|
||||
Attributes:
|
||||
file_id: Provider-specific file identifier.
|
||||
provider: Name of the provider.
|
||||
file_uri: Optional URI for accessing the file.
|
||||
content_type: MIME type of the uploaded file.
|
||||
uploaded_at: When the file was uploaded.
|
||||
expires_at: When the upload expires (if applicable).
|
||||
"""
|
||||
|
||||
file_id: str
|
||||
provider: ProviderType
|
||||
file_uri: str | None
|
||||
content_type: str
|
||||
uploaded_at: datetime
|
||||
expires_at: datetime | None = None
|
||||
|
||||
def is_expired(self) -> bool:
|
||||
"""Check if this cached upload has expired."""
|
||||
if self.expires_at is None:
|
||||
return False
|
||||
return datetime.now(timezone.utc) >= self.expires_at
|
||||
|
||||
|
||||
def _make_key(file_hash: str, provider: str) -> str:
|
||||
"""Create a cache key from file hash and provider."""
|
||||
return f"upload:{provider}:{file_hash}"
|
||||
|
||||
|
||||
def _compute_file_hash_streaming(chunks: Iterator[bytes]) -> str:
|
||||
"""Compute SHA-256 hash from streaming chunks.
|
||||
|
||||
Args:
|
||||
chunks: Iterator of byte chunks.
|
||||
|
||||
Returns:
|
||||
Hexadecimal hash string.
|
||||
"""
|
||||
hasher = hashlib.sha256()
|
||||
for chunk in chunks:
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def _compute_file_hash(file: FileInput) -> str:
|
||||
"""Compute SHA-256 hash of file content.
|
||||
|
||||
Uses streaming for FilePath sources to avoid loading large files into memory.
|
||||
"""
|
||||
from crewai_files.core.sources import FilePath
|
||||
|
||||
source = file._file_source
|
||||
if isinstance(source, FilePath):
|
||||
return _compute_file_hash_streaming(source.read_chunks(chunk_size=1024 * 1024))
|
||||
content = file.read()
|
||||
return hashlib.sha256(content).hexdigest()
|
||||
|
||||
|
||||
class UploadCache:
|
||||
"""Async cache for tracking uploaded files using aiocache.
|
||||
|
||||
Supports in-memory caching by default, with optional Redis backend
|
||||
for distributed setups.
|
||||
|
||||
Attributes:
|
||||
ttl: Default time-to-live in seconds for cached entries.
|
||||
namespace: Cache namespace for isolation.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
ttl: int = DEFAULT_TTL_SECONDS,
|
||||
namespace: str = "crewai_uploads",
|
||||
cache_type: str = "memory",
|
||||
max_entries: int | None = DEFAULT_MAX_CACHE_ENTRIES,
|
||||
**cache_kwargs: Any,
|
||||
) -> None:
|
||||
"""Initialize the upload cache.
|
||||
|
||||
Args:
|
||||
ttl: Default TTL in seconds.
|
||||
namespace: Cache namespace.
|
||||
cache_type: Backend type ("memory" or "redis").
|
||||
max_entries: Maximum cache entries (None for unlimited).
|
||||
**cache_kwargs: Additional args for cache backend.
|
||||
"""
|
||||
self.ttl = ttl
|
||||
self.namespace = namespace
|
||||
self.max_entries = max_entries
|
||||
self._provider_keys: dict[ProviderType, set[str]] = {}
|
||||
self._key_access_order: list[str] = []
|
||||
|
||||
if cache_type == "redis":
|
||||
self._cache = Cache(
|
||||
Cache.REDIS,
|
||||
serializer=PickleSerializer(),
|
||||
namespace=namespace,
|
||||
**cache_kwargs,
|
||||
)
|
||||
else:
|
||||
self._cache = Cache(
|
||||
serializer=PickleSerializer(),
|
||||
namespace=namespace,
|
||||
)
|
||||
|
||||
def _track_key(self, provider: ProviderType, key: str) -> None:
|
||||
"""Track a key for a provider (for cleanup) and access order."""
|
||||
if provider not in self._provider_keys:
|
||||
self._provider_keys[provider] = set()
|
||||
self._provider_keys[provider].add(key)
|
||||
if key in self._key_access_order:
|
||||
self._key_access_order.remove(key)
|
||||
self._key_access_order.append(key)
|
||||
|
||||
def _untrack_key(self, provider: ProviderType, key: str) -> None:
|
||||
"""Remove key tracking for a provider."""
|
||||
if provider in self._provider_keys:
|
||||
self._provider_keys[provider].discard(key)
|
||||
if key in self._key_access_order:
|
||||
self._key_access_order.remove(key)
|
||||
|
||||
async def _evict_if_needed(self) -> int:
|
||||
"""Evict oldest entries if limit exceeded.
|
||||
|
||||
Returns:
|
||||
Number of entries evicted.
|
||||
"""
|
||||
if self.max_entries is None:
|
||||
return 0
|
||||
|
||||
current_count = len(self)
|
||||
if current_count < self.max_entries:
|
||||
return 0
|
||||
|
||||
to_evict = max(1, self.max_entries // 10)
|
||||
return await self._evict_oldest(to_evict)
|
||||
|
||||
async def _evict_oldest(self, count: int) -> int:
|
||||
"""Evict the oldest entries from the cache.
|
||||
|
||||
Args:
|
||||
count: Number of entries to evict.
|
||||
|
||||
Returns:
|
||||
Number of entries actually evicted.
|
||||
"""
|
||||
evicted = 0
|
||||
keys_to_evict = self._key_access_order[:count]
|
||||
|
||||
for key in keys_to_evict:
|
||||
await self._cache.delete(key)
|
||||
self._key_access_order.remove(key)
|
||||
for provider_keys in self._provider_keys.values():
|
||||
provider_keys.discard(key)
|
||||
evicted += 1
|
||||
|
||||
if evicted > 0:
|
||||
logger.debug(f"Evicted {evicted} oldest cache entries")
|
||||
|
||||
return evicted
|
||||
|
||||
async def aget(
|
||||
self, file: FileInput, provider: ProviderType
|
||||
) -> CachedUpload | None:
|
||||
"""Get a cached upload for a file.
|
||||
|
||||
Args:
|
||||
file: The file to look up.
|
||||
provider: The provider name.
|
||||
|
||||
Returns:
|
||||
Cached upload if found and not expired, None otherwise.
|
||||
"""
|
||||
file_hash = _compute_file_hash(file)
|
||||
return await self.aget_by_hash(file_hash, provider)
|
||||
|
||||
async def aget_by_hash(
|
||||
self, file_hash: str, provider: ProviderType
|
||||
) -> CachedUpload | None:
|
||||
"""Get a cached upload by file hash.
|
||||
|
||||
Args:
|
||||
file_hash: Hash of the file content.
|
||||
provider: The provider name.
|
||||
|
||||
Returns:
|
||||
Cached upload if found and not expired, None otherwise.
|
||||
"""
|
||||
key = _make_key(file_hash, provider)
|
||||
result = await self._cache.get(key)
|
||||
|
||||
if result is None:
|
||||
return None
|
||||
if isinstance(result, CachedUpload):
|
||||
if result.is_expired():
|
||||
await self._cache.delete(key)
|
||||
self._untrack_key(provider, key)
|
||||
return None
|
||||
return result
|
||||
return None
|
||||
|
||||
async def aset(
|
||||
self,
|
||||
file: FileInput,
|
||||
provider: ProviderType,
|
||||
file_id: str,
|
||||
file_uri: str | None = None,
|
||||
expires_at: datetime | None = None,
|
||||
) -> CachedUpload:
|
||||
"""Cache an uploaded file.
|
||||
|
||||
Args:
|
||||
file: The file that was uploaded.
|
||||
provider: The provider name.
|
||||
file_id: Provider-specific file identifier.
|
||||
file_uri: Optional URI for accessing the file.
|
||||
expires_at: When the upload expires.
|
||||
|
||||
Returns:
|
||||
The created cache entry.
|
||||
"""
|
||||
file_hash = _compute_file_hash(file)
|
||||
return await self.aset_by_hash(
|
||||
file_hash=file_hash,
|
||||
content_type=file.content_type,
|
||||
provider=provider,
|
||||
file_id=file_id,
|
||||
file_uri=file_uri,
|
||||
expires_at=expires_at,
|
||||
)
|
||||
|
||||
async def aset_by_hash(
|
||||
self,
|
||||
file_hash: str,
|
||||
content_type: str,
|
||||
provider: ProviderType,
|
||||
file_id: str,
|
||||
file_uri: str | None = None,
|
||||
expires_at: datetime | None = None,
|
||||
) -> CachedUpload:
|
||||
"""Cache an uploaded file by hash.
|
||||
|
||||
Args:
|
||||
file_hash: Hash of the file content.
|
||||
content_type: MIME type of the file.
|
||||
provider: The provider name.
|
||||
file_id: Provider-specific file identifier.
|
||||
file_uri: Optional URI for accessing the file.
|
||||
expires_at: When the upload expires.
|
||||
|
||||
Returns:
|
||||
The created cache entry.
|
||||
"""
|
||||
await self._evict_if_needed()
|
||||
|
||||
key = _make_key(file_hash, provider)
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
cached = CachedUpload(
|
||||
file_id=file_id,
|
||||
provider=provider,
|
||||
file_uri=file_uri,
|
||||
content_type=content_type,
|
||||
uploaded_at=now,
|
||||
expires_at=expires_at,
|
||||
)
|
||||
|
||||
ttl = self.ttl
|
||||
if expires_at is not None:
|
||||
ttl = max(0, int((expires_at - now).total_seconds()))
|
||||
|
||||
await self._cache.set(key, cached, ttl=ttl)
|
||||
self._track_key(provider, key)
|
||||
logger.debug(f"Cached upload: {file_id} for provider {provider}")
|
||||
return cached
|
||||
|
||||
async def aremove(self, file: FileInput, provider: ProviderType) -> bool:
|
||||
"""Remove a cached upload.
|
||||
|
||||
Args:
|
||||
file: The file to remove.
|
||||
provider: The provider name.
|
||||
|
||||
Returns:
|
||||
True if entry was removed, False if not found.
|
||||
"""
|
||||
file_hash = _compute_file_hash(file)
|
||||
key = _make_key(file_hash, provider)
|
||||
|
||||
result = await self._cache.delete(key)
|
||||
removed = bool(result > 0 if isinstance(result, int) else result)
|
||||
if removed:
|
||||
self._untrack_key(provider, key)
|
||||
return removed
|
||||
|
||||
async def aremove_by_file_id(self, file_id: str, provider: ProviderType) -> bool:
|
||||
"""Remove a cached upload by file ID.
|
||||
|
||||
Args:
|
||||
file_id: The file ID to remove.
|
||||
provider: The provider name.
|
||||
|
||||
Returns:
|
||||
True if entry was removed, False if not found.
|
||||
"""
|
||||
if provider not in self._provider_keys:
|
||||
return False
|
||||
|
||||
for key in list(self._provider_keys[provider]):
|
||||
cached = await self._cache.get(key)
|
||||
if isinstance(cached, CachedUpload) and cached.file_id == file_id:
|
||||
await self._cache.delete(key)
|
||||
self._untrack_key(provider, key)
|
||||
return True
|
||||
return False
|
||||
|
||||
async def aclear_expired(self) -> int:
|
||||
"""Remove all expired entries from the cache.
|
||||
|
||||
Returns:
|
||||
Number of entries removed.
|
||||
"""
|
||||
removed = 0
|
||||
|
||||
for provider, keys in list(self._provider_keys.items()):
|
||||
for key in list(keys):
|
||||
cached = await self._cache.get(key)
|
||||
if cached is None or (
|
||||
isinstance(cached, CachedUpload) and cached.is_expired()
|
||||
):
|
||||
await self._cache.delete(key)
|
||||
self._untrack_key(provider, key)
|
||||
removed += 1
|
||||
|
||||
if removed > 0:
|
||||
logger.debug(f"Cleared {removed} expired cache entries")
|
||||
return removed
|
||||
|
||||
async def aclear(self) -> int:
|
||||
"""Clear all entries from the cache.
|
||||
|
||||
Returns:
|
||||
Number of entries cleared.
|
||||
"""
|
||||
count = sum(len(keys) for keys in self._provider_keys.values())
|
||||
await self._cache.clear(namespace=self.namespace)
|
||||
self._provider_keys.clear()
|
||||
|
||||
if count > 0:
|
||||
logger.debug(f"Cleared {count} cache entries")
|
||||
return count
|
||||
|
||||
async def aget_all_for_provider(self, provider: ProviderType) -> list[CachedUpload]:
|
||||
"""Get all cached uploads for a provider.
|
||||
|
||||
Args:
|
||||
provider: The provider name.
|
||||
|
||||
Returns:
|
||||
List of cached uploads for the provider.
|
||||
"""
|
||||
if provider not in self._provider_keys:
|
||||
return []
|
||||
|
||||
results: list[CachedUpload] = []
|
||||
for key in list(self._provider_keys[provider]):
|
||||
cached = await self._cache.get(key)
|
||||
if isinstance(cached, CachedUpload) and not cached.is_expired():
|
||||
results.append(cached)
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def _run_sync(coro: Any) -> Any:
|
||||
"""Run an async coroutine from sync context without blocking event loop."""
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
except RuntimeError:
|
||||
loop = None
|
||||
|
||||
if loop is not None and loop.is_running():
|
||||
future = asyncio.run_coroutine_threadsafe(coro, loop)
|
||||
return future.result(timeout=30)
|
||||
return asyncio.run(coro)
|
||||
|
||||
def get(self, file: FileInput, provider: ProviderType) -> CachedUpload | None:
|
||||
"""Sync wrapper for aget."""
|
||||
result: CachedUpload | None = self._run_sync(self.aget(file, provider))
|
||||
return result
|
||||
|
||||
def get_by_hash(
|
||||
self, file_hash: str, provider: ProviderType
|
||||
) -> CachedUpload | None:
|
||||
"""Sync wrapper for aget_by_hash."""
|
||||
result: CachedUpload | None = self._run_sync(
|
||||
self.aget_by_hash(file_hash, provider)
|
||||
)
|
||||
return result
|
||||
|
||||
def set(
|
||||
self,
|
||||
file: FileInput,
|
||||
provider: ProviderType,
|
||||
file_id: str,
|
||||
file_uri: str | None = None,
|
||||
expires_at: datetime | None = None,
|
||||
) -> CachedUpload:
|
||||
"""Sync wrapper for aset."""
|
||||
result: CachedUpload = self._run_sync(
|
||||
self.aset(file, provider, file_id, file_uri, expires_at)
|
||||
)
|
||||
return result
|
||||
|
||||
def set_by_hash(
|
||||
self,
|
||||
file_hash: str,
|
||||
content_type: str,
|
||||
provider: ProviderType,
|
||||
file_id: str,
|
||||
file_uri: str | None = None,
|
||||
expires_at: datetime | None = None,
|
||||
) -> CachedUpload:
|
||||
"""Sync wrapper for aset_by_hash."""
|
||||
result: CachedUpload = self._run_sync(
|
||||
self.aset_by_hash(
|
||||
file_hash, content_type, provider, file_id, file_uri, expires_at
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
def remove(self, file: FileInput, provider: ProviderType) -> bool:
|
||||
"""Sync wrapper for aremove."""
|
||||
result: bool = self._run_sync(self.aremove(file, provider))
|
||||
return result
|
||||
|
||||
def remove_by_file_id(self, file_id: str, provider: ProviderType) -> bool:
|
||||
"""Sync wrapper for aremove_by_file_id."""
|
||||
result: bool = self._run_sync(self.aremove_by_file_id(file_id, provider))
|
||||
return result
|
||||
|
||||
def clear_expired(self) -> int:
|
||||
"""Sync wrapper for aclear_expired."""
|
||||
result: int = self._run_sync(self.aclear_expired())
|
||||
return result
|
||||
|
||||
def clear(self) -> int:
|
||||
"""Sync wrapper for aclear."""
|
||||
result: int = self._run_sync(self.aclear())
|
||||
return result
|
||||
|
||||
def get_all_for_provider(self, provider: ProviderType) -> list[CachedUpload]:
|
||||
"""Sync wrapper for aget_all_for_provider."""
|
||||
result: list[CachedUpload] = self._run_sync(
|
||||
self.aget_all_for_provider(provider)
|
||||
)
|
||||
return result
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Return the number of cached entries."""
|
||||
return sum(len(keys) for keys in self._provider_keys.values())
|
||||
|
||||
def get_providers(self) -> builtins.set[ProviderType]:
|
||||
"""Get all provider names that have cached entries.
|
||||
|
||||
Returns:
|
||||
Set of provider names.
|
||||
"""
|
||||
return builtins.set(self._provider_keys.keys())
|
||||
|
||||
|
||||
_default_cache: UploadCache | None = None
|
||||
|
||||
|
||||
def get_upload_cache(
|
||||
ttl: int = DEFAULT_TTL_SECONDS,
|
||||
namespace: str = "crewai_uploads",
|
||||
cache_type: str = "memory",
|
||||
**cache_kwargs: Any,
|
||||
) -> UploadCache:
|
||||
"""Get or create the default upload cache.
|
||||
|
||||
Args:
|
||||
ttl: Default TTL in seconds.
|
||||
namespace: Cache namespace.
|
||||
cache_type: Backend type ("memory" or "redis").
|
||||
**cache_kwargs: Additional args for cache backend.
|
||||
|
||||
Returns:
|
||||
The upload cache instance.
|
||||
"""
|
||||
global _default_cache
|
||||
if _default_cache is None:
|
||||
_default_cache = UploadCache(
|
||||
ttl=ttl,
|
||||
namespace=namespace,
|
||||
cache_type=cache_type,
|
||||
**cache_kwargs,
|
||||
)
|
||||
return _default_cache
|
||||
|
||||
|
||||
def reset_upload_cache() -> None:
|
||||
"""Reset the default upload cache (useful for testing)."""
|
||||
global _default_cache
|
||||
if _default_cache is not None:
|
||||
_default_cache.clear()
|
||||
_default_cache = None
|
||||
|
||||
|
||||
def _cleanup_on_exit() -> None:
|
||||
"""Clean up uploaded files on process exit."""
|
||||
global _default_cache
|
||||
if _default_cache is None or len(_default_cache) == 0:
|
||||
return
|
||||
|
||||
from crewai_files.cache.cleanup import cleanup_uploaded_files
|
||||
|
||||
try:
|
||||
cleanup_uploaded_files(_default_cache)
|
||||
except Exception as e:
|
||||
logger.debug(f"Error during exit cleanup: {e}")
|
||||
|
||||
|
||||
atexit.register(_cleanup_on_exit)
|
||||
92
lib/crewai-files/src/crewai_files/core/__init__.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""Core file types and sources."""
|
||||
|
||||
from crewai_files.core.constants import (
|
||||
BACKOFF_BASE_DELAY,
|
||||
BACKOFF_JITTER_FACTOR,
|
||||
BACKOFF_MAX_DELAY,
|
||||
DEFAULT_MAX_CACHE_ENTRIES,
|
||||
DEFAULT_MAX_FILE_SIZE_BYTES,
|
||||
DEFAULT_TTL_SECONDS,
|
||||
DEFAULT_UPLOAD_CHUNK_SIZE,
|
||||
FILES_API_MAX_SIZE,
|
||||
GEMINI_FILE_TTL,
|
||||
MAGIC_BUFFER_SIZE,
|
||||
MAX_CONCURRENCY,
|
||||
MULTIPART_CHUNKSIZE,
|
||||
MULTIPART_THRESHOLD,
|
||||
UPLOAD_MAX_RETRIES,
|
||||
UPLOAD_RETRY_DELAY_BASE,
|
||||
)
|
||||
from crewai_files.core.resolved import (
|
||||
FileReference,
|
||||
InlineBase64,
|
||||
InlineBytes,
|
||||
ResolvedFile,
|
||||
UrlReference,
|
||||
)
|
||||
from crewai_files.core.sources import (
|
||||
AsyncFileStream,
|
||||
FileBytes,
|
||||
FilePath,
|
||||
FileSource,
|
||||
FileStream,
|
||||
FileUrl,
|
||||
)
|
||||
from crewai_files.core.types import (
|
||||
AudioFile,
|
||||
AudioMimeType,
|
||||
BaseFile,
|
||||
CoercedFileSource,
|
||||
File,
|
||||
FileInput,
|
||||
FileMode,
|
||||
ImageFile,
|
||||
ImageMimeType,
|
||||
PDFFile,
|
||||
TextFile,
|
||||
VideoFile,
|
||||
VideoMimeType,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"BACKOFF_BASE_DELAY",
|
||||
"BACKOFF_JITTER_FACTOR",
|
||||
"BACKOFF_MAX_DELAY",
|
||||
"DEFAULT_MAX_CACHE_ENTRIES",
|
||||
"DEFAULT_MAX_FILE_SIZE_BYTES",
|
||||
"DEFAULT_TTL_SECONDS",
|
||||
"DEFAULT_UPLOAD_CHUNK_SIZE",
|
||||
"FILES_API_MAX_SIZE",
|
||||
"GEMINI_FILE_TTL",
|
||||
"MAGIC_BUFFER_SIZE",
|
||||
"MAX_CONCURRENCY",
|
||||
"MULTIPART_CHUNKSIZE",
|
||||
"MULTIPART_THRESHOLD",
|
||||
"UPLOAD_MAX_RETRIES",
|
||||
"UPLOAD_RETRY_DELAY_BASE",
|
||||
"AsyncFileStream",
|
||||
"AudioFile",
|
||||
"AudioMimeType",
|
||||
"BaseFile",
|
||||
"CoercedFileSource",
|
||||
"File",
|
||||
"FileBytes",
|
||||
"FileInput",
|
||||
"FileMode",
|
||||
"FilePath",
|
||||
"FileReference",
|
||||
"FileSource",
|
||||
"FileStream",
|
||||
"FileUrl",
|
||||
"ImageFile",
|
||||
"ImageMimeType",
|
||||
"InlineBase64",
|
||||
"InlineBytes",
|
||||
"PDFFile",
|
||||
"ResolvedFile",
|
||||
"TextFile",
|
||||
"UrlReference",
|
||||
"VideoFile",
|
||||
"VideoMimeType",
|
||||
]
|
||||
26
lib/crewai-files/src/crewai_files/core/constants.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""Constants for file handling utilities."""
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Final, Literal
|
||||
|
||||
|
||||
DEFAULT_MAX_FILE_SIZE_BYTES: Final[Literal[524_288_000]] = 524_288_000
|
||||
MAGIC_BUFFER_SIZE: Final[Literal[2048]] = 2048
|
||||
|
||||
UPLOAD_MAX_RETRIES: Final[Literal[3]] = 3
|
||||
UPLOAD_RETRY_DELAY_BASE: Final[Literal[2]] = 2
|
||||
|
||||
DEFAULT_TTL_SECONDS: Final[Literal[86_400]] = 86_400
|
||||
DEFAULT_MAX_CACHE_ENTRIES: Final[Literal[1000]] = 1000
|
||||
|
||||
GEMINI_FILE_TTL: Final[timedelta] = timedelta(hours=48)
|
||||
BACKOFF_BASE_DELAY: Final[float] = 1.0
|
||||
BACKOFF_MAX_DELAY: Final[float] = 30.0
|
||||
BACKOFF_JITTER_FACTOR: Final[float] = 0.1
|
||||
|
||||
FILES_API_MAX_SIZE: Final[Literal[536_870_912]] = 536_870_912
|
||||
DEFAULT_UPLOAD_CHUNK_SIZE: Final[Literal[67_108_864]] = 67_108_864
|
||||
|
||||
MULTIPART_THRESHOLD: Final[Literal[8_388_608]] = 8_388_608
|
||||
MULTIPART_CHUNKSIZE: Final[Literal[8_388_608]] = 8_388_608
|
||||
MAX_CONCURRENCY: Final[Literal[10]] = 10
|
||||
84
lib/crewai-files/src/crewai_files/core/resolved.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""Resolved file types representing different delivery methods for file content."""
|
||||
|
||||
from abc import ABC
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedFile(ABC):
|
||||
"""Base class for resolved file representations.
|
||||
|
||||
A ResolvedFile represents the final form of a file ready for delivery
|
||||
to an LLM provider, whether inline or via reference.
|
||||
|
||||
Attributes:
|
||||
content_type: MIME type of the file content.
|
||||
"""
|
||||
|
||||
content_type: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class InlineBase64(ResolvedFile):
|
||||
"""File content encoded as base64 string.
|
||||
|
||||
Used by most providers for inline file content in messages.
|
||||
|
||||
Attributes:
|
||||
content_type: MIME type of the file content.
|
||||
data: Base64-encoded file content.
|
||||
"""
|
||||
|
||||
data: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class InlineBytes(ResolvedFile):
|
||||
"""File content as raw bytes.
|
||||
|
||||
Used by providers like Bedrock that accept raw bytes instead of base64.
|
||||
|
||||
Attributes:
|
||||
content_type: MIME type of the file content.
|
||||
data: Raw file bytes.
|
||||
"""
|
||||
|
||||
data: bytes
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FileReference(ResolvedFile):
|
||||
"""Reference to an uploaded file.
|
||||
|
||||
Used when files are uploaded via provider File APIs.
|
||||
|
||||
Attributes:
|
||||
content_type: MIME type of the file content.
|
||||
file_id: Provider-specific file identifier.
|
||||
provider: Name of the provider the file was uploaded to.
|
||||
expires_at: When the uploaded file expires (if applicable).
|
||||
file_uri: Optional URI for accessing the file (used by Gemini).
|
||||
"""
|
||||
|
||||
file_id: str
|
||||
provider: str
|
||||
expires_at: datetime | None = None
|
||||
file_uri: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class UrlReference(ResolvedFile):
|
||||
"""Reference to a file accessible via URL.
|
||||
|
||||
Used by providers that support fetching files from URLs.
|
||||
|
||||
Attributes:
|
||||
content_type: MIME type of the file content.
|
||||
url: URL where the file can be accessed.
|
||||
"""
|
||||
|
||||
url: str
|
||||
|
||||
|
||||
ResolvedFileType = InlineBase64 | InlineBytes | FileReference | UrlReference
|
||||
529
lib/crewai-files/src/crewai_files/core/sources.py
Normal file
@@ -0,0 +1,529 @@
|
||||
"""Base file class for handling file inputs in tasks."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import AsyncIterator, Iterator
|
||||
import inspect
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Any, BinaryIO, Protocol, cast, runtime_checkable
|
||||
|
||||
import aiofiles
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
BeforeValidator,
|
||||
Field,
|
||||
GetCoreSchemaHandler,
|
||||
PrivateAttr,
|
||||
model_validator,
|
||||
)
|
||||
from pydantic_core import CoreSchema, core_schema
|
||||
from typing_extensions import TypeIs
|
||||
|
||||
from crewai_files.core.constants import DEFAULT_MAX_FILE_SIZE_BYTES, MAGIC_BUFFER_SIZE
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class AsyncReadable(Protocol):
|
||||
"""Protocol for async readable streams."""
|
||||
|
||||
async def read(self, size: int = -1) -> bytes:
|
||||
"""Read up to size bytes from the stream."""
|
||||
...
|
||||
|
||||
|
||||
class _AsyncReadableValidator:
|
||||
"""Pydantic validator for AsyncReadable types."""
|
||||
|
||||
@classmethod
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, _source_type: Any, _handler: GetCoreSchemaHandler
|
||||
) -> CoreSchema:
|
||||
return core_schema.no_info_plain_validator_function(
|
||||
cls._validate,
|
||||
serialization=core_schema.plain_serializer_function_ser_schema(
|
||||
lambda x: None, info_arg=False
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _validate(value: Any) -> AsyncReadable:
|
||||
if isinstance(value, AsyncReadable):
|
||||
return value
|
||||
raise ValueError("Expected an async readable object with async read() method")
|
||||
|
||||
|
||||
ValidatedAsyncReadable = Annotated[AsyncReadable, _AsyncReadableValidator()]
|
||||
|
||||
|
||||
def _fallback_content_type(filename: str | None) -> str:
|
||||
"""Get content type from filename extension or return default."""
|
||||
if filename:
|
||||
mime_type, _ = mimetypes.guess_type(filename)
|
||||
if mime_type:
|
||||
return mime_type
|
||||
return "application/octet-stream"
|
||||
|
||||
|
||||
def generate_filename(content_type: str) -> str:
|
||||
"""Generate a UUID-based filename with extension from content type.
|
||||
|
||||
Args:
|
||||
content_type: MIME type to derive extension from.
|
||||
|
||||
Returns:
|
||||
Filename in format "{uuid}{ext}" where ext includes the dot.
|
||||
"""
|
||||
import uuid
|
||||
|
||||
ext = mimetypes.guess_extension(content_type) or ""
|
||||
return f"{uuid.uuid4()}{ext}"
|
||||
|
||||
|
||||
def detect_content_type(data: bytes, filename: str | None = None) -> str:
|
||||
"""Detect MIME type from file content.
|
||||
|
||||
Uses python-magic if available for accurate content-based detection,
|
||||
falls back to mimetypes module using filename extension.
|
||||
|
||||
Args:
|
||||
data: Raw bytes to analyze (only first 2048 bytes are used).
|
||||
filename: Optional filename for extension-based fallback.
|
||||
|
||||
Returns:
|
||||
The detected MIME type.
|
||||
"""
|
||||
try:
|
||||
import magic
|
||||
|
||||
result: str = magic.from_buffer(data[:MAGIC_BUFFER_SIZE], mime=True)
|
||||
return result
|
||||
except ImportError:
|
||||
return _fallback_content_type(filename)
|
||||
|
||||
|
||||
def detect_content_type_from_path(path: Path, filename: str | None = None) -> str:
|
||||
"""Detect MIME type from file path.
|
||||
|
||||
Uses python-magic's from_file() for accurate detection without reading
|
||||
the entire file into memory.
|
||||
|
||||
Args:
|
||||
path: Path to the file.
|
||||
filename: Optional filename for extension-based fallback.
|
||||
|
||||
Returns:
|
||||
The detected MIME type.
|
||||
"""
|
||||
try:
|
||||
import magic
|
||||
|
||||
result: str = magic.from_file(str(path), mime=True)
|
||||
return result
|
||||
except ImportError:
|
||||
return _fallback_content_type(filename or path.name)
|
||||
|
||||
|
||||
class _BinaryIOValidator:
|
||||
"""Pydantic validator for BinaryIO types."""
|
||||
|
||||
@classmethod
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, _source_type: Any, _handler: GetCoreSchemaHandler
|
||||
) -> CoreSchema:
|
||||
return core_schema.no_info_plain_validator_function(
|
||||
cls._validate,
|
||||
serialization=core_schema.plain_serializer_function_ser_schema(
|
||||
lambda x: None, info_arg=False
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _validate(value: Any) -> BinaryIO:
|
||||
if hasattr(value, "read") and hasattr(value, "seek"):
|
||||
return cast(BinaryIO, value)
|
||||
raise ValueError("Expected a binary file-like object with read() and seek()")
|
||||
|
||||
|
||||
ValidatedBinaryIO = Annotated[BinaryIO, _BinaryIOValidator()]
|
||||
|
||||
|
||||
class FilePath(BaseModel):
|
||||
"""File loaded from a filesystem path."""
|
||||
|
||||
path: Path = Field(description="Path to the file on the filesystem.")
|
||||
max_size_bytes: int = Field(
|
||||
default=DEFAULT_MAX_FILE_SIZE_BYTES,
|
||||
exclude=True,
|
||||
description="Maximum file size in bytes.",
|
||||
)
|
||||
_content: bytes | None = PrivateAttr(default=None)
|
||||
_content_type: str = PrivateAttr()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _validate_file_exists(self) -> FilePath:
|
||||
"""Validate that the file exists, is secure, and within size limits."""
|
||||
from crewai_files.processing.exceptions import FileTooLargeError
|
||||
|
||||
path_str = str(self.path)
|
||||
if ".." in path_str:
|
||||
raise ValueError(f"Path traversal not allowed: {self.path}")
|
||||
|
||||
if self.path.is_symlink():
|
||||
resolved = self.path.resolve()
|
||||
cwd = Path.cwd().resolve()
|
||||
if not str(resolved).startswith(str(cwd)):
|
||||
raise ValueError(f"Symlink escapes allowed directory: {self.path}")
|
||||
|
||||
if not self.path.exists():
|
||||
raise ValueError(f"File not found: {self.path}")
|
||||
if not self.path.is_file():
|
||||
raise ValueError(f"Path is not a file: {self.path}")
|
||||
|
||||
actual_size = self.path.stat().st_size
|
||||
if actual_size > self.max_size_bytes:
|
||||
raise FileTooLargeError(
|
||||
f"File exceeds max size ({actual_size} > {self.max_size_bytes})",
|
||||
file_name=str(self.path),
|
||||
actual_size=actual_size,
|
||||
max_size=self.max_size_bytes,
|
||||
)
|
||||
|
||||
self._content_type = detect_content_type_from_path(self.path, self.path.name)
|
||||
return self
|
||||
|
||||
@property
|
||||
def filename(self) -> str:
|
||||
"""Get the filename from the path."""
|
||||
return self.path.name
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type."""
|
||||
return self._content_type
|
||||
|
||||
def read(self) -> bytes:
|
||||
"""Read the file content from disk."""
|
||||
if self._content is None:
|
||||
self._content = self.path.read_bytes()
|
||||
return self._content
|
||||
|
||||
async def aread(self) -> bytes:
|
||||
"""Async read the file content from disk."""
|
||||
if self._content is None:
|
||||
async with aiofiles.open(self.path, "rb") as f:
|
||||
self._content = await f.read()
|
||||
return self._content
|
||||
|
||||
def read_chunks(self, chunk_size: int = 65536) -> Iterator[bytes]:
|
||||
"""Stream file content in chunks without loading entirely into memory.
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of file content.
|
||||
"""
|
||||
with open(self.path, "rb") as f:
|
||||
while chunk := f.read(chunk_size):
|
||||
yield chunk
|
||||
|
||||
async def aread_chunks(self, chunk_size: int = 65536) -> AsyncIterator[bytes]:
|
||||
"""Async streaming for non-blocking I/O.
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of file content.
|
||||
"""
|
||||
async with aiofiles.open(self.path, "rb") as f:
|
||||
while chunk := await f.read(chunk_size):
|
||||
yield chunk
|
||||
|
||||
|
||||
class FileBytes(BaseModel):
|
||||
"""File created from raw bytes content."""
|
||||
|
||||
data: bytes = Field(description="Raw bytes content of the file.")
|
||||
filename: str | None = Field(default=None, description="Optional filename.")
|
||||
_content_type: str = PrivateAttr()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _detect_content_type(self) -> FileBytes:
|
||||
"""Detect and cache content type from data."""
|
||||
self._content_type = detect_content_type(self.data, self.filename)
|
||||
return self
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type."""
|
||||
return self._content_type
|
||||
|
||||
def read(self) -> bytes:
|
||||
"""Return the bytes content."""
|
||||
return self.data
|
||||
|
||||
async def aread(self) -> bytes:
|
||||
"""Async return the bytes content (immediate, already in memory)."""
|
||||
return self.data
|
||||
|
||||
def read_chunks(self, chunk_size: int = 65536) -> Iterator[bytes]:
|
||||
"""Stream bytes content in chunks.
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of bytes content.
|
||||
"""
|
||||
for i in range(0, len(self.data), chunk_size):
|
||||
yield self.data[i : i + chunk_size]
|
||||
|
||||
async def aread_chunks(self, chunk_size: int = 65536) -> AsyncIterator[bytes]:
|
||||
"""Async streaming (immediate yield since already in memory).
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of bytes content.
|
||||
"""
|
||||
for chunk in self.read_chunks(chunk_size):
|
||||
yield chunk
|
||||
|
||||
|
||||
class FileStream(BaseModel):
|
||||
"""File loaded from a file-like stream."""
|
||||
|
||||
stream: ValidatedBinaryIO = Field(description="Binary file stream.")
|
||||
filename: str | None = Field(default=None, description="Optional filename.")
|
||||
_content: bytes | None = PrivateAttr(default=None)
|
||||
_content_type: str = PrivateAttr()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _initialize(self) -> FileStream:
|
||||
"""Extract filename and detect content type."""
|
||||
if self.filename is None:
|
||||
name = getattr(self.stream, "name", None)
|
||||
if name is not None:
|
||||
self.filename = Path(name).name
|
||||
|
||||
position = self.stream.tell()
|
||||
self.stream.seek(0)
|
||||
header = self.stream.read(MAGIC_BUFFER_SIZE)
|
||||
self.stream.seek(position)
|
||||
self._content_type = detect_content_type(header, self.filename)
|
||||
return self
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type."""
|
||||
return self._content_type
|
||||
|
||||
def read(self) -> bytes:
|
||||
"""Read the stream content. Content is cached after first read."""
|
||||
if self._content is None:
|
||||
position = self.stream.tell()
|
||||
self.stream.seek(0)
|
||||
self._content = self.stream.read()
|
||||
self.stream.seek(position)
|
||||
return self._content
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close the underlying stream."""
|
||||
self.stream.close()
|
||||
|
||||
def __enter__(self) -> FileStream:
|
||||
"""Enter context manager."""
|
||||
return self
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type: type[BaseException] | None,
|
||||
exc_val: BaseException | None,
|
||||
exc_tb: Any,
|
||||
) -> None:
|
||||
"""Exit context manager and close stream."""
|
||||
self.close()
|
||||
|
||||
def read_chunks(self, chunk_size: int = 65536) -> Iterator[bytes]:
|
||||
"""Stream from underlying stream in chunks.
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of stream content.
|
||||
"""
|
||||
position = self.stream.tell()
|
||||
self.stream.seek(0)
|
||||
try:
|
||||
while chunk := self.stream.read(chunk_size):
|
||||
yield chunk
|
||||
finally:
|
||||
self.stream.seek(position)
|
||||
|
||||
|
||||
class AsyncFileStream(BaseModel):
|
||||
"""File loaded from an async stream.
|
||||
|
||||
Use for async file handles like aiofiles objects or aiohttp response bodies.
|
||||
This is an async-only type - use aread() instead of read().
|
||||
|
||||
Attributes:
|
||||
stream: Async file-like object with async read() method.
|
||||
filename: Optional filename for the stream.
|
||||
"""
|
||||
|
||||
stream: ValidatedAsyncReadable = Field(
|
||||
description="Async file stream with async read() method."
|
||||
)
|
||||
filename: str | None = Field(default=None, description="Optional filename.")
|
||||
_content: bytes | None = PrivateAttr(default=None)
|
||||
_content_type: str | None = PrivateAttr(default=None)
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type from stream content (cached). Requires aread() first."""
|
||||
if self._content is None:
|
||||
raise RuntimeError("Call aread() first to load content")
|
||||
if self._content_type is None:
|
||||
self._content_type = detect_content_type(self._content, self.filename)
|
||||
return self._content_type
|
||||
|
||||
async def aread(self) -> bytes:
|
||||
"""Async read the stream content. Content is cached after first read."""
|
||||
if self._content is None:
|
||||
self._content = await self.stream.read()
|
||||
return self._content
|
||||
|
||||
async def aclose(self) -> None:
|
||||
"""Async close the underlying stream."""
|
||||
if hasattr(self.stream, "close"):
|
||||
result = self.stream.close()
|
||||
if inspect.isawaitable(result):
|
||||
await result
|
||||
|
||||
async def __aenter__(self) -> AsyncFileStream:
|
||||
"""Async enter context manager."""
|
||||
return self
|
||||
|
||||
async def __aexit__(
|
||||
self,
|
||||
exc_type: type[BaseException] | None,
|
||||
exc_val: BaseException | None,
|
||||
exc_tb: Any,
|
||||
) -> None:
|
||||
"""Async exit context manager and close stream."""
|
||||
await self.aclose()
|
||||
|
||||
async def aread_chunks(self, chunk_size: int = 65536) -> AsyncIterator[bytes]:
|
||||
"""Async stream content in chunks.
|
||||
|
||||
Args:
|
||||
chunk_size: Size of each chunk in bytes.
|
||||
|
||||
Yields:
|
||||
Chunks of stream content.
|
||||
"""
|
||||
while chunk := await self.stream.read(chunk_size):
|
||||
yield chunk
|
||||
|
||||
|
||||
class FileUrl(BaseModel):
|
||||
"""File referenced by URL.
|
||||
|
||||
For providers that support URL references, the URL is passed directly.
|
||||
For providers that don't, content is fetched on demand.
|
||||
|
||||
Attributes:
|
||||
url: URL where the file can be accessed.
|
||||
filename: Optional filename (extracted from URL if not provided).
|
||||
"""
|
||||
|
||||
url: str = Field(description="URL where the file can be accessed.")
|
||||
filename: str | None = Field(default=None, description="Optional filename.")
|
||||
_content_type: str | None = PrivateAttr(default=None)
|
||||
_content: bytes | None = PrivateAttr(default=None)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _validate_url(self) -> FileUrl:
|
||||
"""Validate URL format."""
|
||||
if not self.url.startswith(("http://", "https://")):
|
||||
raise ValueError(f"Invalid URL scheme: {self.url}")
|
||||
return self
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type, guessing from URL extension if not set."""
|
||||
if self._content_type is None:
|
||||
self._content_type = self._guess_content_type()
|
||||
return self._content_type
|
||||
|
||||
def _guess_content_type(self) -> str:
|
||||
"""Guess content type from URL extension."""
|
||||
from urllib.parse import urlparse
|
||||
|
||||
parsed = urlparse(self.url)
|
||||
path = parsed.path
|
||||
guessed, _ = mimetypes.guess_type(path)
|
||||
return guessed or "application/octet-stream"
|
||||
|
||||
def read(self) -> bytes:
|
||||
"""Fetch content from URL (for providers that don't support URL references)."""
|
||||
if self._content is None:
|
||||
import httpx
|
||||
|
||||
response = httpx.get(self.url, follow_redirects=True)
|
||||
response.raise_for_status()
|
||||
self._content = response.content
|
||||
if "content-type" in response.headers:
|
||||
self._content_type = response.headers["content-type"].split(";")[0]
|
||||
return self._content
|
||||
|
||||
async def aread(self) -> bytes:
|
||||
"""Async fetch content from URL."""
|
||||
if self._content is None:
|
||||
import httpx
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(self.url, follow_redirects=True)
|
||||
response.raise_for_status()
|
||||
self._content = response.content
|
||||
if "content-type" in response.headers:
|
||||
self._content_type = response.headers["content-type"].split(";")[0]
|
||||
return self._content
|
||||
|
||||
|
||||
FileSource = FilePath | FileBytes | FileStream | AsyncFileStream | FileUrl
|
||||
|
||||
|
||||
def is_file_source(v: object) -> TypeIs[FileSource]:
|
||||
"""Type guard to narrow input to FileSource."""
|
||||
return isinstance(v, (FilePath, FileBytes, FileStream, FileUrl))
|
||||
|
||||
|
||||
def _normalize_source(value: Any) -> FileSource:
|
||||
"""Convert raw input to appropriate source type."""
|
||||
if isinstance(value, (FilePath, FileBytes, FileStream, AsyncFileStream, FileUrl)):
|
||||
return value
|
||||
if isinstance(value, str):
|
||||
if value.startswith(("http://", "https://")):
|
||||
return FileUrl(url=value)
|
||||
return FilePath(path=Path(value))
|
||||
if isinstance(value, Path):
|
||||
return FilePath(path=value)
|
||||
if isinstance(value, bytes):
|
||||
return FileBytes(data=value)
|
||||
if isinstance(value, AsyncReadable):
|
||||
return AsyncFileStream(stream=value)
|
||||
if hasattr(value, "read") and hasattr(value, "seek"):
|
||||
return FileStream(stream=value)
|
||||
raise ValueError(f"Cannot convert {type(value).__name__} to file source")
|
||||
|
||||
|
||||
RawFileInput = str | Path | bytes
|
||||
FileSourceInput = Annotated[
|
||||
RawFileInput | FileSource, BeforeValidator(_normalize_source)
|
||||
]
|
||||
282
lib/crewai-files/src/crewai_files/core/types.py
Normal file
@@ -0,0 +1,282 @@
|
||||
"""Content-type specific file classes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC
|
||||
from io import IOBase
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Any, BinaryIO, Literal
|
||||
|
||||
from pydantic import BaseModel, Field, GetCoreSchemaHandler
|
||||
from pydantic_core import CoreSchema, core_schema
|
||||
from typing_extensions import Self
|
||||
|
||||
from crewai_files.core.sources import (
|
||||
AsyncFileStream,
|
||||
FileBytes,
|
||||
FilePath,
|
||||
FileSource,
|
||||
FileStream,
|
||||
FileUrl,
|
||||
is_file_source,
|
||||
)
|
||||
|
||||
|
||||
FileSourceInput = str | Path | bytes | IOBase | FileSource
|
||||
|
||||
|
||||
class _FileSourceCoercer:
|
||||
"""Pydantic-compatible type that coerces various inputs to FileSource."""
|
||||
|
||||
@classmethod
|
||||
def _coerce(cls, v: Any) -> FileSource:
|
||||
"""Convert raw input to appropriate FileSource type."""
|
||||
if isinstance(v, (FilePath, FileBytes, FileStream, FileUrl)):
|
||||
return v
|
||||
if isinstance(v, str):
|
||||
if v.startswith(("http://", "https://")):
|
||||
return FileUrl(url=v)
|
||||
return FilePath(path=Path(v))
|
||||
if isinstance(v, Path):
|
||||
return FilePath(path=v)
|
||||
if isinstance(v, bytes):
|
||||
return FileBytes(data=v)
|
||||
if isinstance(v, (IOBase, BinaryIO)):
|
||||
return FileStream(stream=v)
|
||||
raise ValueError(f"Cannot convert {type(v).__name__} to file source")
|
||||
|
||||
@classmethod
|
||||
def __get_pydantic_core_schema__(
|
||||
cls,
|
||||
_source_type: Any,
|
||||
_handler: GetCoreSchemaHandler,
|
||||
) -> CoreSchema:
|
||||
"""Generate Pydantic core schema for FileSource coercion."""
|
||||
return core_schema.no_info_plain_validator_function(
|
||||
cls._coerce,
|
||||
serialization=core_schema.plain_serializer_function_ser_schema(
|
||||
lambda v: v,
|
||||
info_arg=False,
|
||||
return_schema=core_schema.any_schema(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
CoercedFileSource = Annotated[FileSourceInput, _FileSourceCoercer]
|
||||
|
||||
FileMode = Literal["strict", "auto", "warn", "chunk"]
|
||||
|
||||
|
||||
ImageExtension = Literal[
|
||||
".png",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".gif",
|
||||
".webp",
|
||||
".bmp",
|
||||
".tiff",
|
||||
".tif",
|
||||
".svg",
|
||||
".heic",
|
||||
".heif",
|
||||
]
|
||||
ImageMimeType = Literal[
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/gif",
|
||||
"image/webp",
|
||||
"image/bmp",
|
||||
"image/tiff",
|
||||
"image/svg+xml",
|
||||
"image/heic",
|
||||
"image/heif",
|
||||
]
|
||||
|
||||
PDFExtension = Literal[".pdf"]
|
||||
PDFContentType = Literal["application/pdf"]
|
||||
|
||||
TextExtension = Literal[
|
||||
".txt",
|
||||
".md",
|
||||
".rst",
|
||||
".csv",
|
||||
".json",
|
||||
".xml",
|
||||
".yaml",
|
||||
".yml",
|
||||
".html",
|
||||
".htm",
|
||||
".log",
|
||||
".ini",
|
||||
".cfg",
|
||||
".conf",
|
||||
]
|
||||
TextContentType = Literal[
|
||||
"text/plain",
|
||||
"text/markdown",
|
||||
"text/csv",
|
||||
"application/json",
|
||||
"application/xml",
|
||||
"text/xml",
|
||||
"application/x-yaml",
|
||||
"text/yaml",
|
||||
"text/html",
|
||||
]
|
||||
|
||||
AudioExtension = Literal[
|
||||
".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a", ".wma", ".aiff", ".opus"
|
||||
]
|
||||
AudioMimeType = Literal[
|
||||
"audio/mp3",
|
||||
"audio/mpeg",
|
||||
"audio/wav",
|
||||
"audio/x-wav",
|
||||
"audio/ogg",
|
||||
"audio/flac",
|
||||
"audio/aac",
|
||||
"audio/m4a",
|
||||
"audio/mp4",
|
||||
"audio/x-ms-wma",
|
||||
"audio/aiff",
|
||||
"audio/opus",
|
||||
]
|
||||
|
||||
VideoExtension = Literal[
|
||||
".mp4", ".avi", ".mkv", ".mov", ".webm", ".flv", ".wmv", ".m4v", ".mpeg", ".mpg"
|
||||
]
|
||||
VideoMimeType = Literal[
|
||||
"video/mp4",
|
||||
"video/mpeg",
|
||||
"video/webm",
|
||||
"video/quicktime",
|
||||
"video/x-msvideo",
|
||||
"video/x-matroska",
|
||||
"video/x-flv",
|
||||
"video/x-ms-wmv",
|
||||
]
|
||||
|
||||
|
||||
class BaseFile(ABC, BaseModel):
|
||||
"""Abstract base class for typed file wrappers.
|
||||
|
||||
Provides common functionality for all file types including:
|
||||
- File source management
|
||||
- Content reading
|
||||
- Dict unpacking support (`**` syntax)
|
||||
- Per-file mode mode
|
||||
|
||||
Can be unpacked with ** syntax: `{**ImageFile(source="./chart.png")}`
|
||||
which unpacks to: `{"chart": <ImageFile instance>}` using filename stem as key.
|
||||
|
||||
Attributes:
|
||||
source: The underlying file source (path, bytes, or stream).
|
||||
mode: How to handle this file if it exceeds provider limits.
|
||||
"""
|
||||
|
||||
source: CoercedFileSource = Field(description="The underlying file source.")
|
||||
mode: FileMode = Field(
|
||||
default="auto",
|
||||
description="How to handle if file exceeds limits: strict, auto, warn, chunk.",
|
||||
)
|
||||
|
||||
@property
|
||||
def _file_source(self) -> FileSource:
|
||||
"""Get source with narrowed type (always FileSource after validation)."""
|
||||
if is_file_source(self.source):
|
||||
return self.source
|
||||
raise TypeError("source must be a FileSource after validation")
|
||||
|
||||
@property
|
||||
def filename(self) -> str | None:
|
||||
"""Get the filename from the source."""
|
||||
return self._file_source.filename
|
||||
|
||||
@property
|
||||
def content_type(self) -> str:
|
||||
"""Get the content type from the source."""
|
||||
return self._file_source.content_type
|
||||
|
||||
def read(self) -> bytes:
|
||||
"""Read the file content as bytes."""
|
||||
return self._file_source.read() # type: ignore[union-attr]
|
||||
|
||||
async def aread(self) -> bytes:
|
||||
"""Async read the file content as bytes.
|
||||
|
||||
Raises:
|
||||
TypeError: If the underlying source doesn't support async read.
|
||||
"""
|
||||
source = self._file_source
|
||||
if isinstance(source, (FilePath, FileBytes, AsyncFileStream, FileUrl)):
|
||||
return await source.aread()
|
||||
raise TypeError(f"{type(source).__name__} does not support async read")
|
||||
|
||||
def read_text(self, encoding: str = "utf-8") -> str:
|
||||
"""Read the file content as string."""
|
||||
return self.read().decode(encoding)
|
||||
|
||||
@property
|
||||
def _unpack_key(self) -> str:
|
||||
"""Get the key to use when unpacking (filename stem)."""
|
||||
filename = self._file_source.filename
|
||||
if filename:
|
||||
return Path(filename).stem
|
||||
return "file"
|
||||
|
||||
def keys(self) -> list[str]:
|
||||
"""Return keys for dict unpacking."""
|
||||
return [self._unpack_key]
|
||||
|
||||
def __getitem__(self, key: str) -> Self:
|
||||
"""Return self for dict unpacking."""
|
||||
if key == self._unpack_key:
|
||||
return self
|
||||
raise KeyError(key)
|
||||
|
||||
|
||||
class ImageFile(BaseFile):
|
||||
"""File representing an image.
|
||||
|
||||
Supports common image formats: PNG, JPEG, GIF, WebP, BMP, TIFF, SVG.
|
||||
"""
|
||||
|
||||
|
||||
class PDFFile(BaseFile):
|
||||
"""File representing a PDF document."""
|
||||
|
||||
|
||||
class TextFile(BaseFile):
|
||||
"""File representing a text document.
|
||||
|
||||
Supports common text formats: TXT, MD, RST, CSV, JSON, XML, YAML, HTML.
|
||||
"""
|
||||
|
||||
|
||||
class AudioFile(BaseFile):
|
||||
"""File representing an audio file.
|
||||
|
||||
Supports common audio formats: MP3, WAV, OGG, FLAC, AAC, M4A, WMA.
|
||||
"""
|
||||
|
||||
|
||||
class VideoFile(BaseFile):
|
||||
"""File representing a video file.
|
||||
|
||||
Supports common video formats: MP4, AVI, MKV, MOV, WebM, FLV, WMV.
|
||||
"""
|
||||
|
||||
|
||||
class File(BaseFile):
|
||||
"""Generic file that auto-detects the appropriate type.
|
||||
|
||||
Use this when you don't want to specify the exact file type.
|
||||
The content type is automatically detected from the file contents.
|
||||
|
||||
Example:
|
||||
>>> pdf_file = File(source="./document.pdf")
|
||||
>>> image_file = File(source="./image.png")
|
||||
>>> bytes_file = File(source=b"file content")
|
||||
"""
|
||||
|
||||
|
||||
FileInput = AudioFile | File | ImageFile | PDFFile | TextFile | VideoFile
|
||||
14
lib/crewai-files/src/crewai_files/formatting/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""High-level formatting API for multimodal content."""
|
||||
|
||||
from crewai_files.formatting.api import (
|
||||
aformat_multimodal_content,
|
||||
format_multimodal_content,
|
||||
)
|
||||
from crewai_files.formatting.openai import OpenAIResponsesFormatter
|
||||
|
||||
|
||||
__all__ = [
|
||||
"OpenAIResponsesFormatter",
|
||||
"aformat_multimodal_content",
|
||||
"format_multimodal_content",
|
||||
]
|
||||
98
lib/crewai-files/src/crewai_files/formatting/anthropic.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""Anthropic content block formatter."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from typing import Any
|
||||
|
||||
from crewai_files.core.resolved import (
|
||||
FileReference,
|
||||
InlineBase64,
|
||||
InlineBytes,
|
||||
ResolvedFileType,
|
||||
UrlReference,
|
||||
)
|
||||
from crewai_files.core.types import FileInput
|
||||
|
||||
|
||||
class AnthropicFormatter:
|
||||
"""Formats resolved files into Anthropic content blocks."""
|
||||
|
||||
def format_block(
|
||||
self,
|
||||
file: FileInput,
|
||||
resolved: ResolvedFileType,
|
||||
) -> dict[str, Any] | None:
|
||||
"""Format a resolved file into an Anthropic content block.
|
||||
|
||||
Args:
|
||||
file: Original file input with metadata.
|
||||
resolved: Resolved file.
|
||||
|
||||
Returns:
|
||||
Content block dict or None if not supported.
|
||||
"""
|
||||
content_type = file.content_type
|
||||
block_type = self._get_block_type(content_type)
|
||||
if block_type is None:
|
||||
return None
|
||||
|
||||
if isinstance(resolved, FileReference):
|
||||
return {
|
||||
"type": block_type,
|
||||
"source": {
|
||||
"type": "file",
|
||||
"file_id": resolved.file_id,
|
||||
},
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
|
||||
if isinstance(resolved, UrlReference):
|
||||
return {
|
||||
"type": block_type,
|
||||
"source": {
|
||||
"type": "url",
|
||||
"url": resolved.url,
|
||||
},
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
|
||||
if isinstance(resolved, InlineBase64):
|
||||
return {
|
||||
"type": block_type,
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": resolved.content_type,
|
||||
"data": resolved.data,
|
||||
},
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
|
||||
if isinstance(resolved, InlineBytes):
|
||||
return {
|
||||
"type": block_type,
|
||||
"source": {
|
||||
"type": "base64",
|
||||
"media_type": resolved.content_type,
|
||||
"data": base64.b64encode(resolved.data).decode("ascii"),
|
||||
},
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
}
|
||||
|
||||
raise TypeError(f"Unexpected resolved type: {type(resolved).__name__}")
|
||||
|
||||
@staticmethod
|
||||
def _get_block_type(content_type: str) -> str | None:
|
||||
"""Get Anthropic block type for content type.
|
||||
|
||||
Args:
|
||||
content_type: MIME type.
|
||||
|
||||
Returns:
|
||||
Block type string or None if not supported.
|
||||
"""
|
||||
if content_type.startswith("image/"):
|
||||
return "image"
|
||||
if content_type == "application/pdf":
|
||||
return "document"
|
||||
return None
|
||||